pedimentos UI

This commit is contained in:
Galindo97
2025-12-23 14:15:05 -06:00
parent d3a0086188
commit 150efdfd99
61 changed files with 1033 additions and 256 deletions

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -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')

View File

@@ -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(

View File

@@ -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"

View File

@@ -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

View File

@@ -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):

View File

@@ -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")

View File

@@ -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")

View File

@@ -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"""

View File

@@ -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"
)

View File

@@ -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

View File

@@ -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")

View File

@@ -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")

View File

@@ -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(

View File

@@ -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"
)

View File

@@ -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"
)

View File

@@ -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"
)

View File

@@ -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")

View File

@@ -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"

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"
)

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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 (

View File

@@ -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}")