From 150efdfd9903eb4b7a7f5533f0508d163b920324 Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Tue, 23 Dec 2025 14:15:05 -0600 Subject: [PATCH 1/3] pedimentos UI --- ...14d_change_config_parameters_to_boolean.py | 118 ++++++++++ .../8de9bb2a4c1b_make_status_nullable.py | 34 +++ ...ad1cb8_update_config_calculations_types.py | 113 ++++++++++ ...c441c57f_add_observations_to_pedimentos.py | 31 +++ backend/api/v1/common/tenant_crud_routes.py | 42 +++- .../dtos/pedimento_config_additional.py | 4 +- .../dtos/pedimento_config_calculations.py | 38 ++-- .../dtos/pedimento_config_parameters.py | 58 ++--- .../dtos/pedimento_config_surcharges.py | 4 +- .../pedimento_config_update_rectification.py | 4 +- .../dtos/pedimento_config_updates.py | 4 +- .../dtos/pedimento_customs_offices.py | 4 +- .../a76/pedmientos/dtos/pedimento_dates.py | 9 +- .../dtos/pedimento_decrementables.py | 4 +- .../dtos/pedimento_incrementables.py | 4 +- .../a76/pedmientos/dtos/pedimento_indexes.py | 4 +- .../a76/pedmientos/dtos/pedimento_payments.py | 4 +- .../pedimento_rectification_destination.py | 4 +- .../dtos/pedimento_rectification_origin.py | 4 +- .../dtos/pedimento_transport_means.py | 4 +- .../pedmientos/dtos/pedimento_validation.py | 4 +- .../modules/a76/pedmientos/dtos/pedimentos.py | 9 +- .../models/pedimento_config_calculations.py | 23 +- .../models/pedimento_config_parameters.py | 23 +- .../a76/pedmientos/models/pedimentos.py | 35 +-- .../services/pedimento_config_parameters.py | 2 +- .../services/pedimento_config_surcharges.py | 2 +- .../pedimento_config_update_rectification.py | 2 +- .../services/pedimento_config_updates.py | 2 +- .../services/pedimento_customs_offices.py | 2 +- .../pedmientos/services/pedimento_dates.py | 2 +- .../services/pedimento_decrementables.py | 2 +- .../services/pedimento_incrementables.py | 2 +- .../pedmientos/services/pedimento_indexes.py | 2 +- .../pedmientos/services/pedimento_payments.py | 2 +- .../pedimento_rectification_destination.py | 2 +- .../pedimento_rectification_origin.py | 2 +- .../services/pedimento_transport_means.py | 2 +- .../services/pedimento_validation.py | 2 +- .../a76/pedmientos/services/pedimentos.py | 32 ++- docker-compose.yml | 2 +- frontend/package.json | 3 +- frontend/pnpm-lock.yaml | 23 ++ frontend/src/hooks.ts | 3 +- .../lib/api/dashboard/a76/exchange-rate.ts | 13 +- .../src/lib/api/dashboard/a76/pedimentos.ts | 87 +++++++- .../dashboard/pedimentos/columns.ts | 21 +- .../pedimentos/data-table-actions.svelte | 4 +- ... => accounts-compensation-tab-form.svelte} | 0 ...m.svelte => contributions-tab-form.svelte} | 2 +- .../pedimentos/edit/dates-tab-form.svelte | 20 +- ...rm.svelte => digitization-tab-form.svelte} | 0 ...-form.svelte => discharge-tab-form.svelte} | 0 .../pedimentos/edit/general-tab-form.svelte | 28 ++- .../edit/identifiers-tab-form.svelte | 174 +++++++++++++++ ...b-form.svelte => invoices-tab-form.svelte} | 0 ...-tab-form.svelte => items-tab-form.svelte} | 0 ...form.svelte => other-data-tab-form.svelte} | 51 +++-- ...=> package-transportation-tab-form.svelte} | 0 .../pedimentos/edit/[id]/+page.svelte | 210 +++++++++++++++--- frontend/tsconfig.json | 3 +- 61 files changed, 1033 insertions(+), 256 deletions(-) create mode 100644 backend/alembic/versions/7c4a2cee214d_change_config_parameters_to_boolean.py create mode 100644 backend/alembic/versions/8de9bb2a4c1b_make_status_nullable.py create mode 100644 backend/alembic/versions/b83a80ad1cb8_update_config_calculations_types.py create mode 100644 backend/alembic/versions/e34fc441c57f_add_observations_to_pedimentos.py rename frontend/src/lib/components/dashboard/pedimentos/edit/{cuentas-compensacion-tab-form.svelte => accounts-compensation-tab-form.svelte} (100%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{contribuciones-tab-form.svelte => contributions-tab-form.svelte} (99%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{digitalizacion-tab-form.svelte => digitization-tab-form.svelte} (100%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{descargas-tab-form.svelte => discharge-tab-form.svelte} (100%) create mode 100644 frontend/src/lib/components/dashboard/pedimentos/edit/identifiers-tab-form.svelte rename frontend/src/lib/components/dashboard/pedimentos/edit/{facturas-tab-form.svelte => invoices-tab-form.svelte} (100%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{partidas-tab-form.svelte => items-tab-form.svelte} (100%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{otros-datos-tab-form.svelte => other-data-tab-form.svelte} (99%) rename frontend/src/lib/components/dashboard/pedimentos/edit/{bultos-transportes-tab-form.svelte => package-transportation-tab-form.svelte} (100%) diff --git a/backend/alembic/versions/7c4a2cee214d_change_config_parameters_to_boolean.py b/backend/alembic/versions/7c4a2cee214d_change_config_parameters_to_boolean.py new file mode 100644 index 00000000..1fc6af64 --- /dev/null +++ b/backend/alembic/versions/7c4a2cee214d_change_config_parameters_to_boolean.py @@ -0,0 +1,118 @@ +"""change_config_parameters_to_boolean + +Revision ID: 7c4a2cee214d +Revises: 8de9bb2a4c1b +Create Date: 2025-12-26 23:15:47.125136 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '7c4a2cee214d' +down_revision: Union[str, Sequence[str], None] = '8de9bb2a4c1b' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # Change SmallInteger columns to Boolean with default False + op.alter_column('pedimento_config_parameters', 'is_embassy', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'rule_3121_section_ii', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'use_previous_tariff', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'use_payment_date_fi', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'add_state_supplier_record_505', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'customs_value_calculation', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'two_decimals_unit_value', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'customs_value_per_item', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'is_national_supplier', + type_=sa.Boolean(), + server_default='false', + schema='a76') + op.alter_column('pedimento_config_parameters', 'is_consolidated', + type_=sa.Boolean(), + server_default='false', + schema='a76') + + # Change embassy_dta to have default value + op.alter_column('pedimento_config_parameters', 'embassy_dta', + server_default='0.00', + schema='a76') + + +def downgrade() -> None: + """Downgrade schema.""" + # Revert to SmallInteger + op.alter_column('pedimento_config_parameters', 'is_embassy', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'rule_3121_section_ii', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'use_previous_tariff', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'use_payment_date_fi', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'add_state_supplier_record_505', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'customs_value_calculation', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'two_decimals_unit_value', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'customs_value_per_item', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'is_national_supplier', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + op.alter_column('pedimento_config_parameters', 'is_consolidated', + type_=sa.SmallInteger(), + server_default=None, + schema='a76') + + # Remove default from embassy_dta + op.alter_column('pedimento_config_parameters', 'embassy_dta', + server_default=None, + schema='a76') diff --git a/backend/alembic/versions/8de9bb2a4c1b_make_status_nullable.py b/backend/alembic/versions/8de9bb2a4c1b_make_status_nullable.py new file mode 100644 index 00000000..e0c57078 --- /dev/null +++ b/backend/alembic/versions/8de9bb2a4c1b_make_status_nullable.py @@ -0,0 +1,34 @@ +"""make_status_nullable + +Revision ID: 8de9bb2a4c1b +Revises: e34fc441c57f +Create Date: 2025-12-26 22:48:03.475946 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '8de9bb2a4c1b' +down_revision: Union[str, Sequence[str], None] = 'e34fc441c57f' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + op.alter_column('pedimentos', 'status', + existing_type=sa.String(30), + nullable=True, + schema='a76') + + +def downgrade() -> None: + """Downgrade schema.""" + op.alter_column('pedimentos', 'status', + existing_type=sa.String(30), + nullable=False, + schema='a76') diff --git a/backend/alembic/versions/b83a80ad1cb8_update_config_calculations_types.py b/backend/alembic/versions/b83a80ad1cb8_update_config_calculations_types.py new file mode 100644 index 00000000..ff54e1e2 --- /dev/null +++ b/backend/alembic/versions/b83a80ad1cb8_update_config_calculations_types.py @@ -0,0 +1,113 @@ +"""update_config_calculations_types + +Revision ID: b83a80ad1cb8 +Revises: 7c4a2cee214d +Create Date: 2025-12-26 23:52:00.464690 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'b83a80ad1cb8' +down_revision: Union[str, Sequence[str], None] = '7c4a2cee214d' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # Make dta_type nullable + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN dta_type DROP NOT NULL') + + # Change SmallInteger to Boolean with defaults using USING clause + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN dta_operation TYPE boolean USING (dta_operation::boolean), + ALTER COLUMN dta_operation SET DEFAULT false + ''') + + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN dta_vehicle_count SET DEFAULT 0') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN dta_mixed_rate_8permil TYPE boolean USING (dta_mixed_rate_8permil::boolean), + ALTER COLUMN dta_mixed_rate_8permil SET DEFAULT false + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN pays_vat TYPE boolean USING (pays_vat::boolean), + ALTER COLUMN pays_vat SET DEFAULT false + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN pays_prevalidation TYPE boolean USING (pays_prevalidation::boolean), + ALTER COLUMN pays_prevalidation SET DEFAULT false + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN include_sagar_certificate_fee TYPE boolean USING (include_sagar_certificate_fee::boolean), + ALTER COLUMN include_sagar_certificate_fee SET DEFAULT false + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN fixed_vehicle_dta_fee TYPE boolean USING (fixed_vehicle_dta_fee::boolean), + ALTER COLUMN fixed_vehicle_dta_fee SET DEFAULT false + ''') + + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN additional_fixed_fee SET DEFAULT 0') + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN additional_fixed_fee_payment_method DROP NOT NULL') + + +def downgrade() -> None: + """Downgrade schema.""" + # Revert changes + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN dta_type SET NOT NULL') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN dta_operation TYPE smallint USING (dta_operation::int::smallint), + ALTER COLUMN dta_operation DROP DEFAULT + ''') + + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN dta_vehicle_count DROP DEFAULT') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN dta_mixed_rate_8permil TYPE smallint USING (dta_mixed_rate_8permil::int::smallint), + ALTER COLUMN dta_mixed_rate_8permil DROP DEFAULT + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN pays_vat TYPE smallint USING (pays_vat::int::smallint), + ALTER COLUMN pays_vat DROP DEFAULT + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN pays_prevalidation TYPE smallint USING (pays_prevalidation::int::smallint), + ALTER COLUMN pays_prevalidation DROP DEFAULT + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN include_sagar_certificate_fee TYPE smallint USING (include_sagar_certificate_fee::int::smallint), + ALTER COLUMN include_sagar_certificate_fee DROP DEFAULT + ''') + + op.execute(''' + ALTER TABLE a76.pedimento_config_calculations + ALTER COLUMN fixed_vehicle_dta_fee TYPE smallint USING (fixed_vehicle_dta_fee::int::smallint), + ALTER COLUMN fixed_vehicle_dta_fee DROP DEFAULT + ''') + + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN additional_fixed_fee DROP DEFAULT') + op.execute('ALTER TABLE a76.pedimento_config_calculations ALTER COLUMN additional_fixed_fee_payment_method SET NOT NULL') diff --git a/backend/alembic/versions/e34fc441c57f_add_observations_to_pedimentos.py b/backend/alembic/versions/e34fc441c57f_add_observations_to_pedimentos.py new file mode 100644 index 00000000..e9d8a5bf --- /dev/null +++ b/backend/alembic/versions/e34fc441c57f_add_observations_to_pedimentos.py @@ -0,0 +1,31 @@ +"""add_observations_to_pedimentos + +Revision ID: e34fc441c57f +Revises: 3a012dff0274 +Create Date: 2025-12-26 20:26:46.308358 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'e34fc441c57f' +down_revision: Union[str, Sequence[str], None] = '3a012dff0274' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + op.add_column('pedimentos', + sa.Column('observations', sa.Text(), nullable=True), + schema='a76' + ) + + +def downgrade() -> None: + """Downgrade schema.""" + op.drop_column('pedimentos', 'observations', schema='a76') diff --git a/backend/api/v1/common/tenant_crud_routes.py b/backend/api/v1/common/tenant_crud_routes.py index 9a3c65ae..3ff9b0a0 100644 --- a/backend/api/v1/common/tenant_crud_routes.py +++ b/backend/api/v1/common/tenant_crud_routes.py @@ -301,8 +301,15 @@ class TenantCRUDRoutes( db, company_id, current_user) # For child resources, parent_id validation would go here - resource = self.service.create(db, data, tenant_id, company_id) - return resource + try: + resource = self.service.create(db, data, tenant_id, company_id) + return resource + except ValueError as e: + # Capturar errores de validación (como duplicados) + raise HTTPException(status_code=400, detail=str(e)) + except Exception as e: + # Re-lanzar otros errores + raise else: # Parent resource - no parent_id needed @@ -324,8 +331,15 @@ class TenantCRUDRoutes( ): tenant_id = validate_access_to_resource( db, company_id, current_user) - resource = self.service.create(db, data, tenant_id, company_id) - return resource + try: + resource = self.service.create(db, data, tenant_id, company_id) + return resource + except ValueError as e: + # Capturar errores de validación (como duplicados) + raise HTTPException(status_code=400, detail=str(e)) + except Exception as e: + # Re-lanzar otros errores + raise # PUT route # For parent resources: PUT /{id} @@ -353,9 +367,13 @@ class TenantCRUDRoutes( db, company_id, current_user) parent_id = path_params.get(self.parent_id_name) - resource = self.service.update( - db, parent_id, tenant_id, data, company_id - ) + try: + resource = self.service.update( + db, parent_id, tenant_id, data, company_id + ) + except ValueError as e: + # Capturar errores de validación (como duplicados) + raise HTTPException(status_code=400, detail=str(e)) if not resource: raise HTTPException( @@ -388,9 +406,13 @@ class TenantCRUDRoutes( tenant_id = validate_access_to_resource( db, company_id, current_user) - resource = self.service.update( - db, resource_id, tenant_id, data, company_id - ) + try: + resource = self.service.update( + db, resource_id, tenant_id, data, company_id + ) + except ValueError as e: + # Capturar errores de validación (como duplicados) + raise HTTPException(status_code=400, detail=str(e)) if not resource: raise HTTPException( diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_additional.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_additional.py index 028a1dd4..225994dc 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_additional.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_additional.py @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoConfigAdditionalBase(BaseModel): """Base schema for Pedimento Config Additional""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") add_po_identifier: Optional[int] = Field(None, description="Add PO identifier") do_not_exempt_norms_complement_x: Optional[int] = Field( None, description="Do not exempt norms complement X" diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_calculations.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_calculations.py index 692b9e9c..74fc640e 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_calculations.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_calculations.py @@ -7,24 +7,24 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoConfigCalculationsBase(BaseModel): """Base schema for Pedimento Config Calculations""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") dta_type: Optional[str] = Field(None, max_length=1, description="DTA type") - dta_operation: Optional[int] = Field(None, description="DTA operation") - dta_vehicle_count: Optional[int] = Field(None, description="DTA vehicle count") - dta_mixed_rate_8permil: Optional[int] = Field( - None, description="DTA mixed rate 8 per mil" + dta_operation: Optional[bool] = Field(False, description="DTA operation") + dta_vehicle_count: Optional[int] = Field(0, description="DTA vehicle count") + dta_mixed_rate_8permil: Optional[bool] = Field( + False, description="DTA mixed rate 8 per mil" ) - pays_vat: Optional[int] = Field(None, description="Pays VAT") - pays_prevalidation: Optional[int] = Field(None, description="Pays prevalidation") - include_sagar_certificate_fee: Optional[int] = Field( - None, description="Include SAGAR certificate fee" + pays_vat: Optional[bool] = Field(False, description="Pays VAT") + pays_prevalidation: Optional[bool] = Field(False, description="Pays prevalidation") + include_sagar_certificate_fee: Optional[bool] = Field( + False, description="Include SAGAR certificate fee" ) - fixed_vehicle_dta_fee: Optional[int] = Field( - None, description="Fixed vehicle DTA fee" + fixed_vehicle_dta_fee: Optional[bool] = Field( + False, description="Fixed vehicle DTA fee" ) additional_fixed_fee: Optional[int] = Field( - None, description="Additional fixed fee" + 0, description="Additional fixed fee" ) additional_fixed_fee_payment_method: Optional[int] = Field( None, description="Additional fixed fee payment method" @@ -41,13 +41,13 @@ class PedimentoConfigCalculationsUpdate(BaseModel): """Schema for updating a Pedimento Config Calculations""" dta_type: Optional[str] = Field(None, max_length=1) - dta_operation: Optional[int] = None + dta_operation: Optional[bool] = None dta_vehicle_count: Optional[int] = None - dta_mixed_rate_8permil: Optional[int] = None - pays_vat: Optional[int] = None - pays_prevalidation: Optional[int] = None - include_sagar_certificate_fee: Optional[int] = None - fixed_vehicle_dta_fee: Optional[int] = None + dta_mixed_rate_8permil: Optional[bool] = None + pays_vat: Optional[bool] = None + pays_prevalidation: Optional[bool] = None + include_sagar_certificate_fee: Optional[bool] = None + fixed_vehicle_dta_fee: Optional[bool] = None additional_fixed_fee: Optional[int] = None additional_fixed_fee_payment_method: Optional[int] = None diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_parameters.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_parameters.py index 3f5f04ed..d04a03e4 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_parameters.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_parameters.py @@ -8,31 +8,31 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoConfigParametersBase(BaseModel): """Base schema for Pedimento Config Parameters""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") - is_embassy: Optional[int] = Field(None, description="Is embassy") - embassy_dta: Optional[Decimal] = Field(None, description="Embassy DTA") - rule_3121_section_ii: Optional[int] = Field( - None, description="Rule 3.1.21 Section II" + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") + is_embassy: Optional[bool] = Field(False, description="Is embassy") + embassy_dta: Optional[Decimal] = Field(Decimal('0.00'), description="Embassy DTA") + rule_3121_section_ii: Optional[bool] = Field( + False, description="Rule 3.1.21 Section II" ) - use_previous_tariff: Optional[int] = Field(None, description="Use previous tariff") - use_payment_date_fi: Optional[int] = Field(None, description="Use payment date FI") - add_state_supplier_record_505: Optional[int] = Field( - None, description="Add state supplier record 505" + use_previous_tariff: Optional[bool] = Field(False, description="Use previous tariff") + use_payment_date_fi: Optional[bool] = Field(False, description="Use payment date FI") + add_state_supplier_record_505: Optional[bool] = Field( + False, description="Add state supplier record 505" ) - customs_value_calculation: Optional[int] = Field( - None, description="Customs value calculation" + customs_value_calculation: Optional[bool] = Field( + False, description="Customs value calculation" ) - two_decimals_unit_value: Optional[int] = Field( - None, description="Two decimals unit value" + two_decimals_unit_value: Optional[bool] = Field( + False, description="Two decimals unit value" ) - customs_value_per_item: Optional[int] = Field( - None, description="Customs value per item" + customs_value_per_item: Optional[bool] = Field( + False, description="Customs value per item" ) - is_national_supplier: Optional[int] = Field( - None, description="Is national supplier" + is_national_supplier: Optional[bool] = Field( + False, description="Is national supplier" ) - is_consolidated: Optional[int] = Field(None, description="Is consolidated") + is_consolidated: Optional[bool] = Field(False, description="Is consolidated") class PedimentoConfigParametersCreate(PedimentoConfigParametersBase): @@ -44,17 +44,17 @@ class PedimentoConfigParametersCreate(PedimentoConfigParametersBase): class PedimentoConfigParametersUpdate(BaseModel): """Schema for updating a Pedimento Config Parameters""" - is_embassy: Optional[int] = None + is_embassy: Optional[bool] = None embassy_dta: Optional[Decimal] = None - rule_3121_section_ii: Optional[int] = None - use_previous_tariff: Optional[int] = None - use_payment_date_fi: Optional[int] = None - add_state_supplier_record_505: Optional[int] = None - customs_value_calculation: Optional[int] = None - two_decimals_unit_value: Optional[int] = None - customs_value_per_item: Optional[int] = None - is_national_supplier: Optional[int] = None - is_consolidated: Optional[int] = None + rule_3121_section_ii: Optional[bool] = None + use_previous_tariff: Optional[bool] = None + use_payment_date_fi: Optional[bool] = None + add_state_supplier_record_505: Optional[bool] = None + customs_value_calculation: Optional[bool] = None + two_decimals_unit_value: Optional[bool] = None + customs_value_per_item: Optional[bool] = None + is_national_supplier: Optional[bool] = None + is_consolidated: Optional[bool] = None class PedimentoConfigParametersResponse(PedimentoConfigParametersBase): diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_surcharges.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_surcharges.py index 385ebcf9..fb2a6fff 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_surcharges.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_surcharges.py @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoConfigSurchargesBase(BaseModel): """Base schema for Pedimento Config Surcharges""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") surcharge_igi: Optional[int] = Field(None, description="Surcharge IGI") surcharge_dta: Optional[int] = Field(None, description="Surcharge DTA") surcharge_vat: Optional[int] = Field(None, description="Surcharge VAT") diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_update_rectification.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_update_rectification.py index 62bbf8f7..a5747610 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_update_rectification.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_update_rectification.py @@ -9,8 +9,8 @@ from api.v1.common.dto_mixins import UpdateFlagsMixin class PedimentoConfigUpdateRectificationBase(BaseModel, UpdateFlagsMixin): """Base schema for Pedimento Config Update Rectification""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") calculate_surcharge: Optional[int] = Field(None, description="Calculate surcharge") diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_updates.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_updates.py index b3098972..0931d66c 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_updates.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_config_updates.py @@ -9,8 +9,8 @@ from api.v1.common.dto_mixins import UpdateFlagsMixin class PedimentoConfigUpdatesBase(BaseModel, UpdateFlagsMixin): """Base schema for Pedimento Config Updates""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") class PedimentoConfigUpdatesCreate(PedimentoConfigUpdatesBase): """Schema for creating a new Pedimento Config Updates""" diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_customs_offices.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_customs_offices.py index 31444672..7c556e95 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_customs_offices.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_customs_offices.py @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoCustomsOfficesBase(BaseModel): """Base schema for Pedimento Customs Offices""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") dispatch_customs: Optional[str] = Field( None, max_length=3, description="Dispatch customs" ) diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_dates.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_dates.py index dd7f048e..c9c4cb62 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_dates.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_dates.py @@ -7,7 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoDatesBase(BaseModel): """Base schema for Pedimento Dates""" - entry_date: Optional[datetime] = Field(None, description="Entry date") + entry_date: Optional[datetime] = Field(None, description="Entry date") + pedimento_date: Optional[datetime] = Field(None, description="Pedimento date") payment_date: datetime = Field(..., description="Payment date") rectification_payment_date: Optional[datetime] = Field( None, description="Rectification payment date" @@ -23,7 +24,8 @@ class PedimentoDatesBase(BaseModel): class PedimentoDatesCreate(BaseModel): """Schema for creating a new Pedimento Dates - pedimento_id and tenant_id are set by backend""" - entry_date: Optional[datetime] = Field(None, description="Entry date") + entry_date: Optional[datetime] = Field(None, description="Entry date") + pedimento_date: Optional[datetime] = Field(None, description="Pedimento date") payment_date: datetime = Field(..., description="Payment date") rectification_payment_date: Optional[datetime] = Field(None, description="Rectification payment date") extraction_date: Optional[datetime] = Field(None, description="Extraction date") @@ -37,7 +39,8 @@ class PedimentoDatesCreate(BaseModel): class PedimentoDatesUpdate(BaseModel): """Schema for updating a Pedimento Dates""" - entry_date: Optional[datetime] = None + entry_date: Optional[datetime] = None + pedimento_date: Optional[datetime] = None payment_date: Optional[datetime] = None rectification_payment_date: Optional[datetime] = None extraction_date: Optional[datetime] = None diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_decrementables.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_decrementables.py index aabce8cf..c9718994 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_decrementables.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_decrementables.py @@ -8,8 +8,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoDecrementablesBase(BaseModel): """Base schema for Pedimento Decrementables""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") freight: Optional[Decimal] = Field(None, description="Freight") insurance: Optional[Decimal] = Field(None, description="Insurance") loading: Optional[Decimal] = Field(None, description="Loading") diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_incrementables.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_incrementables.py index 59beceb2..acc6312e 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_incrementables.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_incrementables.py @@ -8,8 +8,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoIncrementablesBase(BaseModel): """Base schema for Pedimento Incrementables""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") insured_value: Optional[Decimal] = Field(None, description="Insured value") freight: Optional[Decimal] = Field(None, description="Freight") insurance: Optional[Decimal] = Field(None, description="Insurance") diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_indexes.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_indexes.py index b304abee..0007ba67 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_indexes.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_indexes.py @@ -8,8 +8,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoIndexesBase(BaseModel): """Base schema for Pedimento Indexes""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") update_factor_type: Optional[int] = Field(None, description="Update factor type") update_factor: Optional[Decimal] = Field(None, description="Update factor") manual_update_factor: Optional[int] = Field( diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_payments.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_payments.py index bdd98381..992e02d7 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_payments.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_payments.py @@ -9,8 +9,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoPaymentsBase(BaseModel): """Base schema for Pedimento Payments""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") acknowledgment: Optional[str] = Field( None, max_length=20, description="Acknowledgment" ) diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_destination.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_destination.py index b021cc11..7a39e104 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_destination.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_rectification_destination.py @@ -6,8 +6,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoRectificationDestinationBase(BaseModel): """Base schema for Pedimento Rectification Destination""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") destination_pedimento_year: Optional[str] = Field( None, max_length=2, description="Destination pedimento year" ) 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 93caf94f..8cc56bb3 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 @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoRectificationOriginBase(BaseModel): """Base schema for Pedimento Rectification Origin""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") original_pedimento_year: Optional[str] = Field( None, max_length=2, description="Original pedimento year" ) diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_transport_means.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_transport_means.py index da6fb6aa..ba86131a 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_transport_means.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_transport_means.py @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoTransportMeansBase(BaseModel): """Base schema for Pedimento Transport Means""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") destination: Optional[int] = Field(None, description="Destination") entry_exit: Optional[str] = Field(None, max_length=2, description="Entry/exit") arrival: str = Field(..., max_length=2, description="Arrival") diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_validation.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_validation.py index 649ce3cb..7be73678 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_validation.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimento_validation.py @@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field class PedimentoValidationBase(BaseModel): """Base schema for Pedimento Validation""" - pedimento_id: int = Field(..., description="Pedimento ID") - tenant_id: int = Field(..., description="Tenant ID") + pedimento_id: Optional[int] = Field(None, description="Pedimento ID") + tenant_id: Optional[int] = Field(None, description="Tenant ID") validator: Optional[str] = Field(None, max_length=3, description="Validator") validation_ack: Optional[str] = Field( None, max_length=8, description="Validation acknowledgment" diff --git a/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py b/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py index 32598d75..73e4d64e 100644 --- a/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py +++ b/backend/api/v1/modules/a76/pedmientos/dtos/pedimentos.py @@ -50,7 +50,8 @@ class PedimentosBase(BaseModel): usd_value: Optional[Decimal] = Field(None, description="USD value") paid_price: Optional[Decimal] = Field(None, description="Paid price") gross_weight: Optional[Decimal] = Field(None, description="Gross weight") - exchange_rate: Optional[Decimal] = Field(None, description="Exchange rate") + exchange_rate: Optional[Decimal] = Field(None, description="Exchange rate") + observations: Optional[str] = Field(None, description="Observations") class PedimentosCreate(PedimentosBase): """Schema for creating a new Pedimento""" @@ -61,13 +62,11 @@ class PedimentosCreate(PedimentosBase): license: str = Field(..., max_length=4, description="License") pedimento_number: str = Field(..., max_length=7, description="Pedimento number") client_id: int = Field(..., description="Client ID") - operation_type: int = Field(..., description="Operation type") - pedimento_type: str = Field(..., max_length=20, description="Pedimento type") + # operation_type, pedimento_type, status son opcionales - se pueden llenar después pedimento_code: str = Field( ..., max_length=2, description="Pedimento key" ) - regime: str = Field(..., max_length=3, description="Regime") - status: str = Field(..., max_length=30, description="Status") + regime: str = Field(..., max_length=3, description="Regime") pedimento_dates: Optional[PedimentoDatesCreate] = None pedimento_decrementables: Optional[PedimentoDecrementablesCreate] = None diff --git a/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_calculations.py b/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_calculations.py index 013768fe..3dcb2859 100644 --- a/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_calculations.py +++ b/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_calculations.py @@ -1,8 +1,9 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from api.v1.common.base_models import TenantScopedMixin, TimestampMixin from core.database import Base from sqlalchemy import ( + Boolean, ForeignKeyConstraint, Integer, PrimaryKeyConstraint, @@ -38,16 +39,16 @@ class PedimentoConfigCalculations(Base, TenantScopedMixin, TimestampMixin): id: Mapped[int] = mapped_column(Integer) pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False) - dta_type: Mapped[str] = mapped_column(String(1)) - dta_operation: Mapped[int] = mapped_column(SmallInteger) - dta_vehicle_count: Mapped[int] = mapped_column(SmallInteger) - dta_mixed_rate_8permil: Mapped[int] = mapped_column(SmallInteger) - pays_vat: Mapped[int] = mapped_column(SmallInteger) - pays_prevalidation: Mapped[int] = mapped_column(SmallInteger) - include_sagar_certificate_fee: Mapped[int] = mapped_column(SmallInteger) - fixed_vehicle_dta_fee: Mapped[int] = mapped_column(SmallInteger) - additional_fixed_fee: Mapped[int] = mapped_column(SmallInteger) - additional_fixed_fee_payment_method: Mapped[int] = mapped_column(SmallInteger) + dta_type: Mapped[Optional[str]] = mapped_column(String(1), nullable=True) + dta_operation: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + dta_vehicle_count: Mapped[int] = mapped_column(SmallInteger, default=0, server_default='0') + dta_mixed_rate_8permil: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + pays_vat: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + pays_prevalidation: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + include_sagar_certificate_fee: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + fixed_vehicle_dta_fee: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + additional_fixed_fee: Mapped[int] = mapped_column(SmallInteger, default=0, server_default='0') + additional_fixed_fee_payment_method: Mapped[Optional[int]] = mapped_column(SmallInteger, nullable=True) pedimento: Mapped["Pedimentos"] = relationship( "Pedimentos", back_populates="pedimento_config_calculations" diff --git a/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_parameters.py b/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_parameters.py index 875d46d8..d53bf32b 100644 --- a/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_parameters.py +++ b/backend/api/v1/modules/a76/pedmientos/models/pedimento_config_parameters.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING from api.v1.common.base_models import TenantScopedMixin, TimestampMixin from core.database import Base from sqlalchemy import ( + Boolean, ForeignKeyConstraint, Integer, Numeric, @@ -39,17 +40,17 @@ class PedimentoConfigParameters(Base, TenantScopedMixin, TimestampMixin): id: Mapped[int] = mapped_column(Integer) pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False) - is_embassy: Mapped[int] = mapped_column(SmallInteger) - embassy_dta: Mapped[Decimal] = mapped_column(Numeric(11, 2)) - rule_3121_section_ii: Mapped[int] = mapped_column(SmallInteger) - use_previous_tariff: Mapped[int] = mapped_column(SmallInteger) - use_payment_date_fi: Mapped[int] = mapped_column(SmallInteger) - add_state_supplier_record_505: Mapped[int] = mapped_column(SmallInteger) - customs_value_calculation: Mapped[int] = mapped_column(SmallInteger) - two_decimals_unit_value: Mapped[int] = mapped_column(SmallInteger) - customs_value_per_item: Mapped[int] = mapped_column(SmallInteger) - is_national_supplier: Mapped[int] = mapped_column(SmallInteger) - is_consolidated: Mapped[int] = mapped_column(SmallInteger) + is_embassy: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + embassy_dta: Mapped[Decimal] = mapped_column(Numeric(11, 2), default=Decimal('0.00'), server_default='0.00') + rule_3121_section_ii: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + use_previous_tariff: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + use_payment_date_fi: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + add_state_supplier_record_505: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + customs_value_calculation: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + two_decimals_unit_value: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + customs_value_per_item: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + is_national_supplier: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') + is_consolidated: Mapped[bool] = mapped_column(Boolean, default=False, server_default='false') pedimento: Mapped["Pedimentos"] = relationship( "Pedimentos", back_populates="pedimento_config_parameters" diff --git a/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py b/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py index 3f414f1c..a7950792 100644 --- a/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py +++ b/backend/api/v1/modules/a76/pedmientos/models/pedimentos.py @@ -10,6 +10,7 @@ from sqlalchemy import ( Numeric, PrimaryKeyConstraint, String, + Text, UniqueConstraint, ) from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -102,65 +103,67 @@ class Pedimentos(Base, TenantScopedMixin, TimestampMixin): pedimento_type: Mapped[str] = mapped_column(String(20)) pedimento_code: Mapped[str] = mapped_column(String(2)) regime: Mapped[str] = mapped_column(String(3)) - status: Mapped[str] = mapped_column(String(30)) + status: Mapped[Optional[str]] = mapped_column(String(30)) usd_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(17, 6)) paid_price: Mapped[Optional[Decimal]] = mapped_column(Numeric(17, 6)) gross_weight: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 3)) exchange_rate: Mapped[Optional[Decimal]] = mapped_column(Numeric(9, 5)) + observations: Mapped[Optional[str]] = mapped_column(Text) pedimento_config_additional: Mapped["PedimentoConfigAdditional"] = relationship( - "PedimentoConfigAdditional", uselist=False, back_populates="pedimento" + "PedimentoConfigAdditional", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_config_calculations: Mapped["PedimentoConfigCalculations"] = relationship( - "PedimentoConfigCalculations", uselist=False, back_populates="pedimento" + "PedimentoConfigCalculations", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_config_parameters: Mapped["PedimentoConfigParameters"] = relationship( - "PedimentoConfigParameters", uselist=False, back_populates="pedimento" + "PedimentoConfigParameters", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_config_surcharges: Mapped["PedimentoConfigSurcharges"] = relationship( - "PedimentoConfigSurcharges", uselist=False, back_populates="pedimento" + "PedimentoConfigSurcharges", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_config_update_rectification: Mapped[ "PedimentoConfigUpdateRectification" ] = relationship( - "PedimentoConfigUpdateRectification", uselist=False, back_populates="pedimento" + "PedimentoConfigUpdateRectification", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_config_updates: Mapped["PedimentoConfigUpdates"] = relationship( - "PedimentoConfigUpdates", uselist=False, back_populates="pedimento" + "PedimentoConfigUpdates", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_customs_offices: Mapped["PedimentoCustomsOffices"] = relationship( - "PedimentoCustomsOffices", uselist=False, back_populates="pedimento" + "PedimentoCustomsOffices", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_dates: Mapped["PedimentoDates"] = relationship( - "PedimentoDates", uselist=False, back_populates="pedimento" + "PedimentoDates", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_decrementables: Mapped["PedimentoDecrementables"] = relationship( - "PedimentoDecrementables", uselist=False, back_populates="pedimento" + "PedimentoDecrementables", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_incrementables: Mapped["PedimentoIncrementables"] = relationship( - "PedimentoIncrementables", uselist=False, back_populates="pedimento" + "PedimentoIncrementables", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_indexes: Mapped["PedimentoIndexes"] = relationship( - "PedimentoIndexes", uselist=False, back_populates="pedimento" + "PedimentoIndexes", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_payments: Mapped["PedimentoPayments"] = relationship( - "PedimentoPayments", uselist=False, back_populates="pedimento" + "PedimentoPayments", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_rectification_destination: Mapped["PedimentoRectificationDestination"] = ( relationship( "PedimentoRectificationDestination", uselist=False, back_populates="pedimento", + cascade="all, delete-orphan" ) ) pedimento_rectification_origin: Mapped["PedimentoRectificationOrigin"] = ( relationship( - "PedimentoRectificationOrigin", uselist=False, back_populates="pedimento" + "PedimentoRectificationOrigin", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) ) pedimento_transport_means: Mapped["PedimentoTransportMeans"] = relationship( - "PedimentoTransportMeans", uselist=False, back_populates="pedimento" + "PedimentoTransportMeans", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) pedimento_validation: Mapped["PedimentoValidation"] = relationship( - "PedimentoValidation", uselist=False, back_populates="pedimento" + "PedimentoValidation", uselist=False, back_populates="pedimento", cascade="all, delete-orphan" ) diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_parameters.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_parameters.py index b3a7fab5..321836c0 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_parameters.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_parameters.py @@ -18,7 +18,7 @@ class PedimentoConfigParametersService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoConfigParameters]: """Get config by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_surcharges.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_surcharges.py index 95f15752..a1f13e17 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_surcharges.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_surcharges.py @@ -18,7 +18,7 @@ class PedimentoConfigSurchargesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoConfigSurcharges]: """Get config by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_update_rectification.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_update_rectification.py index 27fb724a..65f0360f 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_update_rectification.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_update_rectification.py @@ -20,7 +20,7 @@ class PedimentoConfigUpdateRectificationService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoConfigUpdateRectification]: """Get config by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_updates.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_updates.py index b602f8f6..562a4a3e 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_updates.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_config_updates.py @@ -18,7 +18,7 @@ class PedimentoConfigUpdatesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoConfigUpdates]: """Get config by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_customs_offices.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_customs_offices.py index 8f8db39e..1cb07a17 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_customs_offices.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_customs_offices.py @@ -18,7 +18,7 @@ class PedimentoCustomsOfficesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoCustomsOffices]: """Get customs offices by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_dates.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_dates.py index 59e6c75a..1736ea2a 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_dates.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_dates.py @@ -18,7 +18,7 @@ class PedimentoDatesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoDates]: """Get dates by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_decrementables.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_decrementables.py index 73b7d690..c7855ea8 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_decrementables.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_decrementables.py @@ -18,7 +18,7 @@ class PedimentoDecrementablesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoDecrementables]: """Get decrementables by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_incrementables.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_incrementables.py index 2cdffadc..9125d295 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_incrementables.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_incrementables.py @@ -18,7 +18,7 @@ class PedimentoIncrementablesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoIncrementables]: """Get incrementables by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_indexes.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_indexes.py index f671a27c..2bce8ed0 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_indexes.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_indexes.py @@ -15,7 +15,7 @@ class PedimentoIndexesService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoIndexes]: """Get indexes by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_payments.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_payments.py index 1b56e2b9..a4b8539b 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_payments.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_payments.py @@ -15,7 +15,7 @@ class PedimentoPaymentsService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoPayments]: """Get payments by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_destination.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_destination.py index de32adfc..b6538b9c 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_destination.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_destination.py @@ -20,7 +20,7 @@ class PedimentoRectificationDestinationService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoRectificationDestination]: """Get rectification destination by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_origin.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_origin.py index 080bec9f..b92db00e 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_origin.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_rectification_origin.py @@ -18,7 +18,7 @@ class PedimentoRectificationOriginService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoRectificationOrigin]: """Get rectification origin by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_transport_means.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_transport_means.py index ae88a3d1..0c6c5e3a 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_transport_means.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_transport_means.py @@ -18,7 +18,7 @@ class PedimentoTransportMeansService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoTransportMeans]: """Get transport means by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimento_validation.py b/backend/api/v1/modules/a76/pedmientos/services/pedimento_validation.py index ecb17148..ceea59e2 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimento_validation.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimento_validation.py @@ -18,7 +18,7 @@ class PedimentoValidationService: @staticmethod def get_by_pedimento_id( - db: Session, pedimento_id: int, tenant_id: int + db: Session, pedimento_id: int, tenant_id: int, company_id: int = None ) -> Optional[PedimentoValidation]: """Get validation by pedimento ID""" return ( diff --git a/backend/api/v1/modules/a76/pedmientos/services/pedimentos.py b/backend/api/v1/modules/a76/pedmientos/services/pedimentos.py index d6506226..89f4e91c 100644 --- a/backend/api/v1/modules/a76/pedmientos/services/pedimentos.py +++ b/backend/api/v1/modules/a76/pedmientos/services/pedimentos.py @@ -8,6 +8,7 @@ from typing import Any, Dict, List, Optional from sqlalchemy import desc from sqlalchemy.orm import Session, joinedload from sqlalchemy.orm import selectinload +from sqlalchemy.exc import IntegrityError from datetime import datetime from ..dtos.pedimentos import PedimentosCreate, PedimentosUpdate @@ -222,10 +223,15 @@ class PedimentosService: def create_related(model_class, data, extra_fields=None): if data or extra_fields: # Inicializar obj_dict desde data si existe, sino como dict vacío - obj_dict = data.model_dump() if data else {} + obj_dict = data.model_dump(exclude_none=True) if data else {} # Agregar campos extra si se proporcionan if extra_fields: obj_dict.update(extra_fields) + # Solo crear si hay datos significativos (más que solo IDs) + significant_fields = {k: v for k, v in obj_dict.items() + if k not in ('pedimento_id', 'tenant_id', 'company_id') and v is not None} + if not significant_fields and not extra_fields: + return obj = model_class(**obj_dict) obj.pedimento_id = pedimento.id obj.tenant_id = tenant_id @@ -272,6 +278,15 @@ class PedimentosService: db.refresh(pedimento) return pedimento + except IntegrityError as e: + db.rollback() + # Detectar si es un error de pedimento duplicado + error_msg = str(e.orig) + if 'pedimentos_unique_key' in error_msg or 'duplicate key value violates unique constraint' in error_msg: + logger.warning(f"Attempted to create duplicate pedimento: {e}") + raise ValueError("Ya existe un pedimento con estos datos (Año, Aduana, Patente, Número)") + logger.error(f"Integrity error creating pedimento: {e}") + raise except Exception as e: db.rollback() logger.error(f"Error creating pedimento with related data: {e}") @@ -329,11 +344,11 @@ class PedimentosService: return existing = service_class.get_by_pedimento_id( - db, pedimento_id, tenant_id) + db, pedimento_id, tenant_id, company_id) if existing: - # Actualizar existente + # Actualizar existente (excluir pedimento_id, tenant_id, company_id) for field, value in data.items(): - if hasattr(existing, field): + if hasattr(existing, field) and field not in ('pedimento_id', 'tenant_id', 'company_id'): setattr(existing, field, value) else: # Crear nuevo @@ -381,6 +396,15 @@ class PedimentosService: db.refresh(pedimento) return pedimento + except IntegrityError as e: + db.rollback() + # Detectar si es un error de pedimento duplicado + error_msg = str(e.orig) + if 'pedimentos_unique_key' in error_msg or 'duplicate key value violates unique constraint' in error_msg: + logger.warning(f"Attempted to update to duplicate pedimento: {e}") + raise ValueError("Ya existe otro pedimento con estos datos (Año, Aduana, Patente, Número)") + logger.error(f"Integrity error updating pedimento: {e}") + raise except Exception as e: db.rollback() logger.error(f"Error updating pedimento with related data: {e}") diff --git a/docker-compose.yml b/docker-compose.yml index c13ae35e..18215907 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -162,7 +162,7 @@ services: - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-dev-secret} - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:5173,http://localhost:3000} ports: - - "5050:8000" + - "8000:8000" depends_on: postgres-a76: condition: service_healthy diff --git a/frontend/package.json b/frontend/package.json index 5845afea..af6b62ab 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -56,6 +56,7 @@ }, "dependencies": { "keycloak-js": "^26.2.1", - "lucide-svelte": "^0.553.0" + "lucide-svelte": "^0.553.0", + "svelte-sonner": "^1.0.7" } } diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 35a56541..bfafc5e5 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: lucide-svelte: specifier: ^0.553.0 version: 0.553.0(svelte@5.40.2) + svelte-sonner: + specifier: ^1.0.7 + version: 1.0.7(svelte@5.40.2) devDependencies: '@eslint/compat': specifier: ^1.4.0 @@ -1675,6 +1678,11 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + runed@0.28.0: + resolution: {integrity: sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==} + peerDependencies: + svelte: ^5.7.0 + runed@0.35.1: resolution: {integrity: sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==} peerDependencies: @@ -1761,6 +1769,11 @@ packages: svelte: optional: true + svelte-sonner@1.0.7: + resolution: {integrity: sha512-1EUFYmd7q/xfs2qCHwJzGPh9n5VJ3X6QjBN10fof2vxgy8fYE7kVfZ7uGnd7i6fQaWIr5KvXcwYXE/cmTEjk5A==} + peerDependencies: + svelte: ^5.0.0 + svelte-toolbelt@0.10.6: resolution: {integrity: sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==} engines: {node: '>=18', pnpm: '>=8.7.0'} @@ -3379,6 +3392,11 @@ snapshots: dependencies: queue-microtask: 1.2.3 + runed@0.28.0(svelte@5.40.2): + dependencies: + esm-env: 1.2.2 + svelte: 5.40.2 + runed@0.35.1(@sveltejs/kit@2.47.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2): dependencies: dequal: 2.0.3 @@ -3460,6 +3478,11 @@ snapshots: optionalDependencies: svelte: 5.40.2 + svelte-sonner@1.0.7(svelte@5.40.2): + dependencies: + runed: 0.28.0(svelte@5.40.2) + svelte: 5.40.2 + svelte-toolbelt@0.10.6(@sveltejs/kit@2.47.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2): dependencies: clsx: 2.1.1 diff --git a/frontend/src/hooks.ts b/frontend/src/hooks.ts index e75600b3..3b0e6d0b 100644 --- a/frontend/src/hooks.ts +++ b/frontend/src/hooks.ts @@ -1,3 +1,4 @@ import { deLocalizeUrl } from '$lib/paraglide/runtime'; +import type { RequestEvent } from '@sveltejs/kit'; -export const reroute = (request) => deLocalizeUrl(request.url).pathname; +export const reroute = (request: { url: string }) => deLocalizeUrl(request.url).pathname; diff --git a/frontend/src/lib/api/dashboard/a76/exchange-rate.ts b/frontend/src/lib/api/dashboard/a76/exchange-rate.ts index 81b14e90..690d3e9c 100644 --- a/frontend/src/lib/api/dashboard/a76/exchange-rate.ts +++ b/frontend/src/lib/api/dashboard/a76/exchange-rate.ts @@ -26,23 +26,32 @@ export interface ExchangeRateListResponse { */ export async function getExchangeRateByDate(date: string, companyId: number): Promise { try { + console.log('📡 [API] Solicitando tipos de cambio para company_id:', companyId); // Get all exchange rates and filter by date on client side const response = await api.get(`/v1/a76/exchange-rate/?company_id=${companyId}`); + console.log('📡 [API] Respuesta recibida:', response.data?.total, 'tipos de cambio'); + if (response.data && response.data.items && response.data.items.length > 0) { // Filter by date and find USD exchange rate const dateOnly = date.split('T')[0]; // Get YYYY-MM-DD part + console.log('🔍 [API] Buscando fecha:', dateOnly, 'en', response.data.items.length, 'registros'); + const matchingRates = response.data.items.filter(rate => { const rateDate = rate.date.split('T')[0]; - return rateDate === dateOnly && rate.foreign_currency === 'USD'; + const matches = rateDate === dateOnly && rate.foreign_currency === 'USD'; + console.log(' - Comparando:', rateDate, '===', dateOnly, '&& USD ===', rate.foreign_currency, '→', matches); + return matches; }); + console.log('✅ [API] Encontrados', matchingRates.length, 'tipos de cambio que coinciden'); return matchingRates.length > 0 ? matchingRates[0] : null; } + console.log('⚠️ [API] No hay datos en la respuesta'); return null; } catch (error) { - console.error('Error fetching exchange rate:', error); + console.error('❌ [API] Error fetching exchange rate:', error); return null; } } diff --git a/frontend/src/lib/api/dashboard/a76/pedimentos.ts b/frontend/src/lib/api/dashboard/a76/pedimentos.ts index fea0001e..adaf29f1 100644 --- a/frontend/src/lib/api/dashboard/a76/pedimentos.ts +++ b/frontend/src/lib/api/dashboard/a76/pedimentos.ts @@ -85,6 +85,69 @@ export interface PedimentoConfigAdditional { add_remove_norms?: number | null; } +export interface PedimentoConfigCalculations { + dta_type?: string | null; + dta_operation?: number | null; + dta_vehicle_count?: number | null; + dta_mixed_rate_8permil?: number | null; + pays_vat?: number | null; + pays_prevalidation?: number | null; + include_sagar_certificate_fee?: number | null; + fixed_vehicle_dta_fee?: number | null; + additional_fixed_fee?: number | null; + additional_fixed_fee_payment_method?: number | null; +} + +export interface PedimentoConfigSurcharges { + surcharge_igi?: number | null; + surcharge_dta?: number | null; + surcharge_vat?: number | null; + surcharge_isan?: number | null; + surcharge_ieps?: number | null; + surcharge_cc?: number | null; +} + +export interface PedimentoConfigParameters { + is_embassy?: number | null; + embassy_dta?: string | null; + rule_3121_section_ii?: number | null; + use_previous_tariff?: number | null; + use_payment_date_fi?: number | null; + add_state_supplier_record_505?: number | null; + customs_value_calculation?: number | null; + two_decimals_unit_value?: number | null; + customs_value_per_item?: number | null; + is_national_supplier?: number | null; + is_consolidated?: number | null; +} + +export interface PedimentoConfigUpdates { + update_vat?: number | null; + update_advalorem?: number | null; + update_dta?: number | null; + update_cc?: number | null; + update_ieps?: number | null; +} + +export interface PedimentoConfigUpdateRectification { + update_vat?: number | null; + update_advalorem?: number | null; + update_cc?: number | null; + update_ieps?: number | null; + calculate_surcharge?: number | null; +} + +export interface Identificador { + id?: number; + pedimento_id?: number; + caso: string; + complemento1: string; + complemento2: string; + complemento3: string; + nodo: string; + observaciones: string; +} + export interface Pedimento { id: number; tenant_id: number; @@ -102,7 +165,7 @@ export interface Pedimento { paid_price?: number | null; gross_weight?: number | null; exchange_rate?: number | null; - observaciones?: string | null; + observations?: string | null; created_at: string; // Sub-resources pedimento_dates?: PedimentoDates | null; @@ -113,6 +176,12 @@ export interface Pedimento { pedimento_decrementables?: PedimentoDecrementables | null; pedimento_indexes?: PedimentoIndexes | null; pedimento_config_additional?: PedimentoConfigAdditional | null; + pedimento_config_calculations?: PedimentoConfigCalculations | null; + pedimento_config_surcharges?: PedimentoConfigSurcharges | null; + pedimento_config_parameters?: PedimentoConfigParameters | null; + pedimento_config_updates?: PedimentoConfigUpdates | null; + pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null; + identificadores?: Identificador[] | null; } export interface PedimentoListResponse { @@ -137,7 +206,7 @@ export interface CreatePedimentoData { paid_price?: number | null; gross_weight?: number | null; exchange_rate?: number | null; - observaciones?: string | null; + observations?: string | null; // Sub-resources pedimento_dates?: PedimentoDates | null; pedimento_payments?: PedimentoPayments | null; @@ -147,6 +216,12 @@ export interface CreatePedimentoData { pedimento_decrementables?: PedimentoDecrementables | null; pedimento_indexes?: PedimentoIndexes | null; pedimento_config_additional?: PedimentoConfigAdditional | null; + pedimento_config_calculations?: PedimentoConfigCalculations | null; + pedimento_config_surcharges?: PedimentoConfigSurcharges | null; + pedimento_config_parameters?: PedimentoConfigParameters | null; + pedimento_config_updates?: PedimentoConfigUpdates | null; + pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null; + identificadores?: Identificador[] | null; } export interface UpdatePedimentoData { @@ -164,7 +239,7 @@ export interface UpdatePedimentoData { paid_price?: number | null; gross_weight?: number | null; exchange_rate?: number | null; - observaciones?: string | null; + observations?: string | null; // Sub-resources pedimento_dates?: PedimentoDates | null; pedimento_payments?: PedimentoPayments | null; @@ -174,6 +249,12 @@ export interface UpdatePedimentoData { pedimento_decrementables?: PedimentoDecrementables | null; pedimento_indexes?: PedimentoIndexes | null; pedimento_config_additional?: PedimentoConfigAdditional | null; + pedimento_config_calculations?: PedimentoConfigCalculations | null; + pedimento_config_surcharges?: PedimentoConfigSurcharges | null; + pedimento_config_parameters?: PedimentoConfigParameters | null; + pedimento_config_updates?: PedimentoConfigUpdates | null; + pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null; + identificadores?: Identificador[] | null; } export interface PedimentoFilters { diff --git a/frontend/src/lib/components/dashboard/pedimentos/columns.ts b/frontend/src/lib/components/dashboard/pedimentos/columns.ts index 4c4bb93e..340ea641 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/columns.ts +++ b/frontend/src/lib/components/dashboard/pedimentos/columns.ts @@ -2,26 +2,7 @@ import type { ColumnDef } from "@tanstack/table-core"; import { renderComponent, renderSnippet } from "$lib/components/ui/data-table/index.js"; import { createRawSnippet } from "svelte"; import DataTableActions from "./data-table-actions.svelte"; - -export type Pedimento = { - id: number; - tenant_id: number; - year?: string | null; - customs_office?: string | null; - license?: string | null; - pedimento_number?: string | null; - client_id?: number | null; - operation_type?: number | null; - pedimento_type?: number | null; - pedimento_code?: string | null; - regime?: string | null; - status?: string | null; - usd_value?: number | null; - paid_price?: number | null; - gross_weight?: number | null; - exchange_rate?: number | null; - created_at: string; -}; +import type { Pedimento } from "$lib/api/dashboard/a76/pedimentos"; /** * Formatea un número como moneda 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 1aa00270..f8a13e0a 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte @@ -2,6 +2,7 @@ import { Button } from "$lib/components/ui/button"; import * as DropdownMenu from "$lib/components/ui/dropdown-menu"; import { pedimentosApi, type Pedimento } from "$lib/api/dashboard/a76/pedimentos"; + import { companyStore } from "$lib/stores/company.svelte"; import { EllipsisVertical, Pencil, LoaderCircle, Trash2 } from 'lucide-svelte'; let { @@ -24,7 +25,8 @@ error = null; try { - const response = await pedimentosApi.delete(item.id); + const companyId = companyStore.activeCompany?.id; + const response = await pedimentosApi.delete(item.id, companyId); if (response.error) { if (response.status === 401) { diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/cuentas-compensacion-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/accounts-compensation-tab-form.svelte similarity index 100% rename from frontend/src/lib/components/dashboard/pedimentos/edit/cuentas-compensacion-tab-form.svelte rename to frontend/src/lib/components/dashboard/pedimentos/edit/accounts-compensation-tab-form.svelte diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/contribuciones-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/contributions-tab-form.svelte similarity index 99% rename from frontend/src/lib/components/dashboard/pedimentos/edit/contribuciones-tab-form.svelte rename to frontend/src/lib/components/dashboard/pedimentos/edit/contributions-tab-form.svelte index b781de36..8cbce24e 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/edit/contribuciones-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/contributions-tab-form.svelte @@ -19,7 +19,7 @@ DialogTitle, DialogFooter } from '$lib/components/ui/dialog'; - import Checkbox from '$lib/components/ui/checkbox/checkbox.svelte'; + import { Checkbox } from '$lib/components/ui/checkbox'; import { Plus, Pencil, 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 index 070c664b..4cc66add 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte @@ -17,14 +17,18 @@ pedimentoNumber?: string; } = $props(); - // Inicializar formData - if (!formData) { - formData = { - observaciones: pedimento?.observaciones || '' - }; - } - - exists = !!pedimento?.observaciones; + // Asegurar que formData siempre tenga un valor por defecto + formData = formData || { observaciones: '' }; + + // Actualizar formData cuando el pedimento cambie + $effect(() => { + if (pedimento?.observations !== undefined) { + formData = { + observaciones: pedimento.observations || '' + }; + exists = !!pedimento.observations; + } + }); // Mapear el tipo de pedimento a un nombre legible const tipoPedimentoNombre = $derived.by(() => { diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/digitalizacion-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte similarity index 100% rename from frontend/src/lib/components/dashboard/pedimentos/edit/digitalizacion-tab-form.svelte rename to frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/descargas-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/discharge-tab-form.svelte similarity index 100% rename from frontend/src/lib/components/dashboard/pedimentos/edit/descargas-tab-form.svelte rename to frontend/src/lib/components/dashboard/pedimentos/edit/discharge-tab-form.svelte 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 index 74c29207..c5d7d51d 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte @@ -11,10 +11,12 @@ import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers'; import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers'; import type { CodePedimentoRegimen } from '$lib/api/dashboard/refrence_data/code_pedimento_regimens'; + import IdentificadoresTabForm from './identifiers-tab-form.svelte'; let { pedimento, formData = $bindable(), + identificadoresFormData = $bindable(), pedimentoCodes = [], customsSections = [], customsBrokers = [], @@ -23,6 +25,7 @@ }: { pedimento: Pedimento | null; formData?: any; + identificadoresFormData?: any; pedimentoCodes?: PedimentoCode[]; customsSections?: CustomsSection[]; customsBrokers?: CustomsBroker[]; @@ -249,19 +252,23 @@ // Obtener automáticamente el tipo de cambio cuando cambie la fecha de entrada $effect(() => { if (formData && formData.entry_date && companyStore.activeCompany) { - console.log('Buscando tipo de cambio para fecha:', formData.entry_date); + console.log('🔍 [TIPO CAMBIO] Buscando para fecha:', formData.entry_date, 'Company ID:', companyStore.activeCompany.id); getExchangeRateByDate(formData.entry_date, companyStore.activeCompany.id) .then(usdRate => { - console.log('Tipo de cambio USD encontrado:', usdRate); + console.log('✅ [TIPO CAMBIO] Respuesta recibida:', usdRate); if (usdRate && formData) { formData.exchange_rate = usdRate.value; - console.log('Tipo de cambio actualizado a:', usdRate.value); + console.log('✅ [TIPO CAMBIO] Actualizado a:', usdRate.value); } else { - console.warn('No se encontró tipo de cambio USD para la fecha:', formData.entry_date); + console.warn('⚠️ [TIPO CAMBIO] No encontrado para fecha:', formData.entry_date); } }) - .catch(err => console.error('Error al obtener tipo de cambio:', err)); + .catch(err => { + console.error('❌ [TIPO CAMBIO] Error:', err); + }); + } else { + console.log('⏭️ [TIPO CAMBIO] Saltado - formData:', !!formData, 'entry_date:', formData?.entry_date, 'company:', !!companyStore.activeCompany); } }); @@ -417,10 +424,9 @@ {:else if activeSection === 'identificadores'} -
-

Campos de Identificadores - Por configurar

-
+ {:else if activeSection === 'indices'}
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/identifiers-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/identifiers-tab-form.svelte new file mode 100644 index 00000000..19463d1c --- /dev/null +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/identifiers-tab-form.svelte @@ -0,0 +1,174 @@ + + + +
+
+

Identificadores

+ +
+ + {#if formData.identificadores.length === 0} +

+ No hay identificadores registrados +

+ {:else} + + + + Caso + Complemento 1 + Complemento 2 + Complemento 3 + Nodo + Observaciones + Acciones + + + + {#each formData.identificadores as identificador, index} + + {identificador.caso} + {identificador.complemento1} + {identificador.complemento2} + {identificador.complemento3} + {identificador.nodo} + {identificador.observaciones} + +
+ + +
+
+
+ {/each} +
+
+ {/if} +
+
+ + + + + + + {editingIdentificadorIndex !== null ? 'Editar' : 'Nuevo'} Identificador + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +