feat: update invoice and item tabs to use 'Datos Soriana' instead of 'Datos Sonana'

refactor: enhance package transportation tab to prevent infinite loops and load data only once

fix: include credentials in fetch request for company data

feat: implement loading of additional pedimento data in edit page, including contributions, packages, transport carriers, guides, seals, and containers

add: create DTOs and models for pedimento contributions, packages, transport carriers, guides, seals, and containers
This commit is contained in:
Galindo97
2026-01-02 18:04:28 -06:00
parent 0b4c385aeb
commit 97a318fdba
27 changed files with 997 additions and 110 deletions

View File

@@ -23,6 +23,7 @@ class PedimentoConfigAdditionalBase(BaseModel):
None, description="Send 502 validation file for consolidated"
)
add_remove_norms: Optional[bool] = Field(None, description="Add/remove norms")
choose_invoice_cove: Optional[bool] = Field(None, description="Choose invoice COVE in items")
class PedimentoConfigAdditionalCreate(PedimentoConfigAdditionalBase):
@@ -40,6 +41,7 @@ class PedimentoConfigAdditionalUpdate(BaseModel):
enable_import_invoice_recipient: Optional[bool] = None
send_502_validation_file_for_consolidated: Optional[bool] = None
add_remove_norms: Optional[bool] = None
choose_invoice_cove: Optional[bool] = None
class PedimentoConfigAdditionalResponse(PedimentoConfigAdditionalBase):

View File

@@ -0,0 +1,49 @@
from decimal import Decimal
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict
class PedimentoContributionBase(BaseModel):
"""Base schema for Pedimento Contribution"""
pedimento_id: Optional[int] = None
contribucion: Optional[str] = None
tipo_tasa: Optional[str] = None
tasa: Optional[Decimal] = None
forma_pago: Optional[str] = None
importe: Optional[Decimal] = None
gravamen: Optional[str] = None
abreviacion: Optional[str] = None
forma_pago_2: Optional[str] = None
importe_2: Optional[Decimal] = None
class PedimentoContributionCreate(PedimentoContributionBase):
"""Schema for creating Pedimento Contribution"""
pass
class PedimentoContributionUpdate(BaseModel):
"""Schema for updating Pedimento Contribution"""
contribucion: Optional[str] = None
tipo_tasa: Optional[str] = None
tasa: Optional[Decimal] = None
forma_pago: Optional[str] = None
importe: Optional[Decimal] = None
gravamen: Optional[str] = None
abreviacion: Optional[str] = None
forma_pago_2: Optional[str] = None
importe_2: Optional[Decimal] = None
class PedimentoContributionResponse(PedimentoContributionBase):
"""Schema for Pedimento Contribution response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)

View File

@@ -9,7 +9,7 @@ class PedimentoDatesBase(BaseModel):
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")
payment_date: Optional[datetime] = Field(None, description="Payment date")
rectification_payment_date: Optional[datetime] = Field(
None, description="Rectification payment date"
)
@@ -26,7 +26,7 @@ class PedimentoDatesCreate(BaseModel):
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")
payment_date: Optional[datetime] = Field(None, description="Payment date")
rectification_payment_date: Optional[datetime] = Field(None, description="Rectification payment date")
extraction_date: Optional[datetime] = Field(None, description="Extraction date")
submission_date: Optional[datetime] = Field(None, description="Submission date")

View File

@@ -0,0 +1,178 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict
class PedimentoPackagesBase(BaseModel):
"""Base schema for Pedimento Packages"""
pedimento_id: Optional[int] = None
quantity: Optional[int] = None
brand: Optional[str] = None
number: Optional[str] = None
vehicles: Optional[int] = None
class PedimentoPackagesCreate(PedimentoPackagesBase):
"""Schema for creating Pedimento Packages"""
pass
class PedimentoPackagesUpdate(BaseModel):
"""Schema for updating Pedimento Packages"""
quantity: Optional[int] = None
brand: Optional[str] = None
number: Optional[str] = None
vehicles: Optional[int] = None
class PedimentoPackagesResponse(PedimentoPackagesBase):
"""Schema for Pedimento Packages response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PedimentoTransportCarrierBase(BaseModel):
"""Base schema for Pedimento Transport Carrier"""
pedimento_id: Optional[int] = None
carrier: Optional[str] = None
rfc: Optional[str] = None
curp: Optional[str] = None
name: Optional[str] = None
address: Optional[str] = None
city: Optional[str] = None
state: Optional[str] = None
country: Optional[str] = None
tax_id: Optional[str] = None
total_packages: Optional[int] = None
identification: Optional[str] = None
class PedimentoTransportCarrierCreate(PedimentoTransportCarrierBase):
"""Schema for creating Pedimento Transport Carrier"""
pass
class PedimentoTransportCarrierUpdate(BaseModel):
"""Schema for updating Pedimento Transport Carrier"""
carrier: Optional[str] = None
rfc: Optional[str] = None
curp: Optional[str] = None
name: Optional[str] = None
address: Optional[str] = None
city: Optional[str] = None
state: Optional[str] = None
country: Optional[str] = None
tax_id: Optional[str] = None
total_packages: Optional[int] = None
identification: Optional[str] = None
class PedimentoTransportCarrierResponse(PedimentoTransportCarrierBase):
"""Schema for Pedimento Transport Carrier response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PedimentoSealBase(BaseModel):
"""Base schema for Pedimento Seal"""
pedimento_id: Optional[int] = None
number: Optional[str] = None
identification: Optional[str] = None
class PedimentoSealCreate(PedimentoSealBase):
"""Schema for creating Pedimento Seal"""
pass
class PedimentoSealUpdate(BaseModel):
"""Schema for updating Pedimento Seal"""
number: Optional[str] = None
identification: Optional[str] = None
class PedimentoSealResponse(PedimentoSealBase):
"""Schema for Pedimento Seal response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PedimentoContainerBase(BaseModel):
"""Base schema for Pedimento Container"""
pedimento_id: Optional[int] = None
number: Optional[str] = None
identification: Optional[str] = None
type: Optional[str] = None
class PedimentoContainerCreate(PedimentoContainerBase):
"""Schema for creating Pedimento Container"""
pass
class PedimentoContainerUpdate(BaseModel):
"""Schema for updating Pedimento Container"""
number: Optional[str] = None
identification: Optional[str] = None
type: Optional[str] = None
class PedimentoContainerResponse(PedimentoContainerBase):
"""Schema for Pedimento Container response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PedimentoGuideBase(BaseModel):
"""Base schema for Pedimento Guide"""
pedimento_id: Optional[int] = None
guide: Optional[str] = None
identifier: Optional[str] = None
class PedimentoGuideCreate(PedimentoGuideBase):
"""Schema for creating Pedimento Guide"""
pass
class PedimentoGuideUpdate(BaseModel):
"""Schema for updating Pedimento Guide"""
guide: Optional[str] = None
identifier: Optional[str] = None
class PedimentoGuideResponse(PedimentoGuideBase):
"""Schema for Pedimento Guide response"""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)

View File

@@ -16,6 +16,22 @@ from .pedimento_dates import PedimentoDatesCreate, PedimentoDatesResponse
from .pedimento_decrementables import PedimentoDecrementablesCreate, PedimentoDecrementablesResponse
from .pedimento_incrementables import PedimentoIncrementablesCreate, PedimentoIncrementablesResponse
from .pedimento_indexes import PedimentoIndexesCreate, PedimentoIndexesResponse
from .pedimento_packages_transport import (
PedimentoContainerCreate,
PedimentoContainerResponse,
PedimentoPackagesCreate,
PedimentoPackagesResponse,
PedimentoSealCreate,
PedimentoSealResponse,
PedimentoTransportCarrierCreate,
PedimentoTransportCarrierResponse,
PedimentoGuideCreate,
PedimentoGuideResponse,
)
from .pedimento_contributions import (
PedimentoContributionCreate,
PedimentoContributionResponse,
)
from .pedimento_payments import PedimentoPaymentsCreate, PedimentoPaymentsResponse
from .pedimento_rectification_destination import PedimentoRectificationDestinationCreate, PedimentoRectificationDestinationResponse
from .pedimento_rectification_origin import PedimentoRectificationOriginCreate, PedimentoRectificationOriginResponse
@@ -121,6 +137,12 @@ class PedimentosUpdate(BaseModel):
pedimento_config_surcharges: Optional[PedimentoConfigSurchargesCreate] = None
pedimento_config_update_rectification: Optional[PedimentoConfigUpdateRectificationCreate] = None
pedimento_config_updates: Optional[PedimentoConfigUpdatesCreate] = None
pedimento_packages: Optional[PedimentoPackagesCreate] = None
pedimento_transport_carriers: Optional[list[PedimentoTransportCarrierCreate]] = None
pedimento_guides: Optional[list[PedimentoGuideCreate]] = None
pedimento_contributions: Optional[list[PedimentoContributionCreate]] = None
pedimento_seals: Optional[list[PedimentoSealCreate]] = None
pedimento_containers: Optional[list[PedimentoContainerCreate]] = None
class PedimentosResponse(PedimentosBase):
@@ -146,5 +168,11 @@ class PedimentosResponse(PedimentosBase):
pedimento_config_surcharges: Optional[PedimentoConfigSurchargesResponse] = None
pedimento_config_update_rectification: Optional[PedimentoConfigUpdateRectificationResponse] = None
pedimento_config_updates: Optional[PedimentoConfigUpdatesResponse] = None
pedimento_packages: Optional[PedimentoPackagesResponse] = None
pedimento_transport_carriers: Optional[list[PedimentoTransportCarrierResponse]] = None
pedimento_guides: Optional[list[PedimentoGuideResponse]] = None
pedimento_contributions: Optional[list[PedimentoContributionResponse]] = None
pedimento_seals: Optional[list[PedimentoSealResponse]] = None
pedimento_containers: Optional[list[PedimentoContainerResponse]] = None
model_config = ConfigDict(from_attributes=True)

View File

@@ -0,0 +1,84 @@
"""Models for pedimentos module"""
# Import all models to ensure they are registered with SQLAlchemy
from api.v1.modules.a76.pedmientos.models.pedimento_config_additional import (
PedimentoConfigAdditional,
)
from api.v1.modules.a76.pedmientos.models.pedimento_config_calculations import (
PedimentoConfigCalculations,
)
from api.v1.modules.a76.pedmientos.models.pedimento_config_parameters import (
PedimentoConfigParameters,
)
from api.v1.modules.a76.pedmientos.models.pedimento_config_surcharges import (
PedimentoConfigSurcharges,
)
from api.v1.modules.a76.pedmientos.models.pedimento_config_update_rectification import (
PedimentoConfigUpdateRectification,
)
from api.v1.modules.a76.pedmientos.models.pedimento_config_updates import (
PedimentoConfigUpdates,
)
from api.v1.modules.a76.pedmientos.models.pedimento_containers import (
PedimentoContainers,
)
from api.v1.modules.a76.pedmientos.models.pedimento_contributions import (
PedimentoContributions,
)
from api.v1.modules.a76.pedmientos.models.pedimento_customs_offices import (
PedimentoCustomsOffices,
)
from api.v1.modules.a76.pedmientos.models.pedimento_dates import PedimentoDates
from api.v1.modules.a76.pedmientos.models.pedimento_decrementables import (
PedimentoDecrementables,
)
from api.v1.modules.a76.pedmientos.models.pedimento_incrementables import (
PedimentoIncrementables,
)
from api.v1.modules.a76.pedmientos.models.pedimento_indexes import PedimentoIndexes
from api.v1.modules.a76.pedmientos.models.pedimento_packages import PedimentoPackages
from api.v1.modules.a76.pedmientos.models.pedimento_payments import PedimentoPayments
from api.v1.modules.a76.pedmientos.models.pedimento_guides import PedimentoGuides
from api.v1.modules.a76.pedmientos.models.pedimento_rectification_destination import (
PedimentoRectificationDestination,
)
from api.v1.modules.a76.pedmientos.models.pedimento_rectification_origin import (
PedimentoRectificationOrigin,
)
from api.v1.modules.a76.pedmientos.models.pedimento_seals import PedimentoSeals
from api.v1.modules.a76.pedmientos.models.pedimento_transport_carriers import (
PedimentoTransportCarriers,
)
from api.v1.modules.a76.pedmientos.models.pedimento_transport_means import (
PedimentoTransportMeans,
)
from api.v1.modules.a76.pedmientos.models.pedimento_validation import (
PedimentoValidation,
)
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
__all__ = [
"Pedimentos",
"PedimentoConfigAdditional",
"PedimentoConfigCalculations",
"PedimentoConfigParameters",
"PedimentoConfigSurcharges",
"PedimentoConfigUpdateRectification",
"PedimentoConfigUpdates",
"PedimentoContainers",
"PedimentoContributions",
"PedimentoCustomsOffices",
"PedimentoDates",
"PedimentoDecrementables",
"PedimentoIncrementables",
"PedimentoIndexes",
"PedimentoPackages",
"PedimentoGuides",
"PedimentoPayments",
"PedimentoRectificationDestination",
"PedimentoRectificationOrigin",
"PedimentoSeals",
"PedimentoTransportCarriers",
"PedimentoTransportMeans",
"PedimentoValidation",
]

View File

@@ -43,6 +43,7 @@ class PedimentoConfigAdditional(Base, TenantScopedMixin, TimestampMixin):
enable_import_invoice_recipient: Mapped[bool] = mapped_column(Boolean, default=False)
send_502_validation_file_for_consolidated: Mapped[bool] = mapped_column(Boolean, default=False)
add_remove_norms: Mapped[bool] = mapped_column(Boolean, default=False)
choose_invoice_cove: Mapped[bool] = mapped_column(Boolean, default=False)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_config_additional"

View File

@@ -0,0 +1,39 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
PrimaryKeyConstraint,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoContainers(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_containers"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_containers_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_containers",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
number: Mapped[str | None] = mapped_column(String(100), nullable=True)
identification: Mapped[str | None] = mapped_column(String(100), nullable=True)
type: Mapped[str | None] = mapped_column(String(50), nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_containers"
)

View File

@@ -0,0 +1,46 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
Numeric,
PrimaryKeyConstraint,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoContributions(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_contributions"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_contributions_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_contributions",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
contribucion: Mapped[str | None] = mapped_column(String(50), nullable=True)
tipo_tasa: Mapped[str | None] = mapped_column(String(100), nullable=True)
tasa: Mapped[Numeric | None] = mapped_column(Numeric(15, 8), nullable=True)
forma_pago: Mapped[str | None] = mapped_column(String(50), nullable=True)
importe: Mapped[Numeric | None] = mapped_column(Numeric(17, 2), nullable=True)
gravamen: Mapped[str | None] = mapped_column(String(100), nullable=True)
abreviacion: Mapped[str | None] = mapped_column(String(50), nullable=True)
forma_pago_2: Mapped[str | None] = mapped_column(String(50), nullable=True)
importe_2: Mapped[Numeric | None] = mapped_column(Numeric(17, 2), nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_contributions"
)

View File

@@ -44,7 +44,7 @@ class PedimentoDates(Base, TenantScopedMixin, TimestampMixin):
entry_date: Mapped[Optional[datetime]] = mapped_column(DateTime)
pedimento_date: Mapped[Optional[datetime]] = mapped_column(DateTime)
payment_date: Mapped[datetime] = mapped_column(DateTime)
payment_date: Mapped[Optional[datetime]] = mapped_column(DateTime)
rectification_payment_date: Mapped[Optional[datetime]] = mapped_column(DateTime)
extraction_date: Mapped[Optional[datetime]] = mapped_column(DateTime)
submission_date: Mapped[Optional[datetime]] = mapped_column(DateTime)

View File

@@ -1,5 +1,5 @@
from decimal import Decimal
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
@@ -40,15 +40,15 @@ class PedimentoDecrementables(Base, TenantScopedMixin, TimestampMixin):
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
freight: Mapped[Decimal] = mapped_column(Numeric(13, 2))
insurance: Mapped[Decimal] = mapped_column(Numeric(13, 2))
loading: Mapped[Decimal] = mapped_column(Numeric(13, 2))
unloading: Mapped[Decimal] = mapped_column(Numeric(13, 2))
others: Mapped[Decimal] = mapped_column(Numeric(13, 2))
currency: Mapped[str] = mapped_column(String(3))
currency_factor: Mapped[Decimal] = mapped_column(Numeric(15, 8))
not_affect_usd_value: Mapped[int] = mapped_column(SmallInteger)
not_affect_customs_value: Mapped[int] = mapped_column(SmallInteger)
freight: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
insurance: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
loading: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
unloading: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
others: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
currency: Mapped[Optional[str]] = mapped_column(String(3))
currency_factor: Mapped[Optional[Decimal]] = mapped_column(Numeric(15, 8))
not_affect_usd_value: Mapped[Optional[int]] = mapped_column(SmallInteger)
not_affect_customs_value: Mapped[Optional[int]] = mapped_column(SmallInteger)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_decrementables"

View File

@@ -0,0 +1,38 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
PrimaryKeyConstraint,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoGuides(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_guides"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_guides_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_guides",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
guide: Mapped[str | None] = mapped_column(String(100), nullable=True)
identifier: Mapped[str | None] = mapped_column(String(100), nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_guides"
)

View File

@@ -1,5 +1,5 @@
from decimal import Decimal
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
@@ -40,16 +40,16 @@ class PedimentoIncrementables(Base, TenantScopedMixin, TimestampMixin):
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
insured_value: Mapped[Decimal] = mapped_column(Numeric(13, 2))
freight: Mapped[Decimal] = mapped_column(Numeric(13, 2))
insurance: Mapped[Decimal] = mapped_column(Numeric(13, 2))
packaging: Mapped[Decimal] = mapped_column(Numeric(13, 2))
others: Mapped[Decimal] = mapped_column(Numeric(13, 3))
deductibles: Mapped[Decimal] = mapped_column(Numeric(13, 3))
currency: Mapped[str] = mapped_column(String(3))
currency_factor: Mapped[Decimal] = mapped_column(Numeric(15, 8))
not_affect_usd_value: Mapped[int] = mapped_column(SmallInteger)
not_affect_customs_value: Mapped[int] = mapped_column(SmallInteger)
insured_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
freight: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
insurance: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
packaging: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 2))
others: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 3))
deductibles: Mapped[Optional[Decimal]] = mapped_column(Numeric(13, 3))
currency: Mapped[Optional[str]] = mapped_column(String(3))
currency_factor: Mapped[Optional[Decimal]] = mapped_column(Numeric(15, 8))
not_affect_usd_value: Mapped[Optional[int]] = mapped_column(SmallInteger)
not_affect_customs_value: Mapped[Optional[int]] = mapped_column(SmallInteger)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_incrementables"

View File

@@ -1,5 +1,5 @@
from decimal import Decimal
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
@@ -39,9 +39,9 @@ class PedimentoIndexes(Base, TenantScopedMixin, TimestampMixin):
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
update_factor_type: Mapped[int] = mapped_column(SmallInteger)
update_factor: Mapped[Decimal] = mapped_column(Numeric(7, 4))
manual_update_factor: Mapped[int] = mapped_column(SmallInteger)
update_factor_type: Mapped[Optional[int]] = mapped_column(SmallInteger)
update_factor: Mapped[Optional[Decimal]] = mapped_column(Numeric(7, 4))
manual_update_factor: Mapped[Optional[int]] = mapped_column(SmallInteger)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_indexes"

View File

@@ -0,0 +1,48 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
Numeric,
PrimaryKeyConstraint,
String,
UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoPackages(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_packages"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_packages_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_packages",
),
UniqueConstraint(
"tenant_id",
"company_id",
"pedimento_id",
name="pedimento_packages_pedimento_id_key",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
quantity: Mapped[int | None] = mapped_column(Integer, nullable=True)
brand: Mapped[str | None] = mapped_column(String(100), nullable=True)
number: Mapped[str | None] = mapped_column(String(100), nullable=True)
vehicles: Mapped[int | None] = mapped_column(Integer, nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_packages"
)

View File

@@ -0,0 +1,38 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
PrimaryKeyConstraint,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoSeals(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_seals"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_seals_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_seals",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
number: Mapped[str | None] = mapped_column(String(100), nullable=True)
identification: Mapped[str | None] = mapped_column(String(100), nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_seals"
)

View File

@@ -0,0 +1,47 @@
from typing import TYPE_CHECKING
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKeyConstraint,
Integer,
PrimaryKeyConstraint,
String,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
class PedimentoTransportCarriers(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "pedimento_transport_carriers"
__table_args__ = (
PrimaryKeyConstraint("id", name="pedimento_transport_carriers_pkey"),
ForeignKeyConstraint(
["pedimento_id"],
["a76.pedimentos.id"],
ondelete="CASCADE",
name="fk_pedimento_transport_carriers",
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
carrier: Mapped[str | None] = mapped_column(String(200), nullable=True)
rfc: Mapped[str | None] = mapped_column(String(20), nullable=True)
curp: Mapped[str | None] = mapped_column(String(20), nullable=True)
name: Mapped[str | None] = mapped_column(String(200), nullable=True)
address: Mapped[str | None] = mapped_column(String(300), nullable=True)
city: Mapped[str | None] = mapped_column(String(100), nullable=True)
state: Mapped[str | None] = mapped_column(String(100), nullable=True)
country: Mapped[str | None] = mapped_column(String(3), nullable=True)
tax_id: Mapped[str | None] = mapped_column(String(50), nullable=True)
total_packages: Mapped[int | None] = mapped_column(Integer, nullable=True)
identification: Mapped[str | None] = mapped_column(String(100), nullable=True)
pedimento: Mapped["Pedimentos"] = relationship(
"Pedimentos", back_populates="pedimento_transport_carriers"
)

View File

@@ -34,6 +34,9 @@ if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimento_config_updates import (
PedimentoConfigUpdates,
)
from api.v1.modules.a76.pedmientos.models.pedimento_containers import (
PedimentoContainers,
)
from api.v1.modules.a76.pedmientos.models.pedimento_customs_offices import (
PedimentoCustomsOffices,
)
@@ -45,6 +48,15 @@ if TYPE_CHECKING:
PedimentoIncrementables,
)
from api.v1.modules.a76.pedmientos.models.pedimento_indexes import PedimentoIndexes
from api.v1.modules.a76.pedmientos.models.pedimento_packages import (
PedimentoPackages,
)
from api.v1.modules.a76.pedmientos.models.pedimento_guides import (
PedimentoGuides,
)
from api.v1.modules.a76.pedmientos.models.pedimento_contributions import (
PedimentoContributions,
)
from api.v1.modules.a76.pedmientos.models.pedimento_payments import (
PedimentoPayments,
)
@@ -54,6 +66,12 @@ if TYPE_CHECKING:
from api.v1.modules.a76.pedmientos.models.pedimento_rectification_origin import (
PedimentoRectificationOrigin,
)
from api.v1.modules.a76.pedmientos.models.pedimento_seals import (
PedimentoSeals,
)
from api.v1.modules.a76.pedmientos.models.pedimento_transport_carriers import (
PedimentoTransportCarriers,
)
from api.v1.modules.a76.pedmientos.models.pedimento_transport_means import (
PedimentoTransportMeans,
)
@@ -167,3 +185,21 @@ class Pedimentos(Base, TenantScopedMixin, TimestampMixin):
pedimento_validation: Mapped["PedimentoValidation"] = relationship(
"PedimentoValidation", uselist=False, back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_packages: Mapped["PedimentoPackages"] = relationship(
"PedimentoPackages", uselist=False, back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_transport_carriers: Mapped[list["PedimentoTransportCarriers"]] = relationship(
"PedimentoTransportCarriers", back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_guides: Mapped[list["PedimentoGuides"]] = relationship(
"PedimentoGuides", back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_contributions: Mapped[list["PedimentoContributions"]] = relationship(
"PedimentoContributions", back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_seals: Mapped[list["PedimentoSeals"]] = relationship(
"PedimentoSeals", back_populates="pedimento", cascade="all, delete-orphan"
)
pedimento_containers: Mapped[list["PedimentoContainers"]] = relationship(
"PedimentoContainers", back_populates="pedimento", cascade="all, delete-orphan"
)

View File

@@ -48,6 +48,12 @@ from ..models.pedimento_config_parameters import PedimentoConfigParameters
from ..models.pedimento_config_surcharges import PedimentoConfigSurcharges
from ..models.pedimento_config_update_rectification import PedimentoConfigUpdateRectification
from ..models.pedimento_config_updates import PedimentoConfigUpdates
from ..models.pedimento_packages import PedimentoPackages
from ..models.pedimento_transport_carriers import PedimentoTransportCarriers
from ..models.pedimento_seals import PedimentoSeals
from ..models.pedimento_containers import PedimentoContainers
from ..models.pedimento_guides import PedimentoGuides
from ..models.pedimento_contributions import PedimentoContributions
logger = logging.getLogger(__name__)
@@ -110,6 +116,12 @@ class PedimentosService:
selectinload(Pedimentos.pedimento_config_surcharges),
selectinload(Pedimentos.pedimento_config_update_rectification),
selectinload(Pedimentos.pedimento_config_updates),
selectinload(Pedimentos.pedimento_packages),
selectinload(Pedimentos.pedimento_transport_carriers),
selectinload(Pedimentos.pedimento_guides),
selectinload(Pedimentos.pedimento_contributions),
selectinload(Pedimentos.pedimento_seals),
selectinload(Pedimentos.pedimento_containers),
)
.order_by(desc(Pedimentos.created_at))
.offset(skip)
@@ -160,6 +172,12 @@ class PedimentosService:
selectinload(Pedimentos.pedimento_config_surcharges),
selectinload(Pedimentos.pedimento_config_update_rectification),
selectinload(Pedimentos.pedimento_config_updates),
selectinload(Pedimentos.pedimento_packages),
selectinload(Pedimentos.pedimento_transport_carriers),
selectinload(Pedimentos.pedimento_guides),
selectinload(Pedimentos.pedimento_contributions),
selectinload(Pedimentos.pedimento_seals),
selectinload(Pedimentos.pedimento_containers),
)
return query.first()
@@ -199,6 +217,12 @@ class PedimentosService:
'pedimento_config_surcharges': pedimento_data.pedimento_config_surcharges,
'pedimento_config_update_rectification': pedimento_data.pedimento_config_update_rectification,
'pedimento_config_updates': pedimento_data.pedimento_config_updates,
'pedimento_packages': pedimento_data.pedimento_packages,
'pedimento_transport_carriers': pedimento_data.pedimento_transport_carriers,
'pedimento_guides': pedimento_data.pedimento_guides,
'pedimento_contributions': getattr(pedimento_data, 'pedimento_contributions', None),
'pedimento_seals': pedimento_data.pedimento_seals,
'pedimento_containers': pedimento_data.pedimento_containers,
}
# Crear pedimento principal (excluyendo relaciones)
@@ -209,7 +233,8 @@ class PedimentosService:
'pedimento_rectification_origin', 'pedimento_transport_means',
'pedimento_config_additional', 'pedimento_config_calculations',
'pedimento_config_parameters', 'pedimento_config_surcharges',
'pedimento_config_update_rectification', 'pedimento_config_updates'
'pedimento_config_update_rectification', 'pedimento_config_updates',
'pedimento_packages', 'pedimento_transport_carriers', 'pedimento_guides', 'pedimento_seals', 'pedimento_containers'
})
pedimento = Pedimentos(**pedimento_dict)
@@ -219,7 +244,7 @@ class PedimentosService:
db.add(pedimento)
db.flush() # Flush para obtener el ID sin commit
# Helper function para crear objetos relacionados
# Helper function para crear objetos relacionados (uno a uno)
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
@@ -274,6 +299,29 @@ class PedimentosService:
create_related(PedimentoConfigUpdates,
related_data['pedimento_config_updates'])
# Crear PedimentoPackages (uno a uno)
create_related(PedimentoPackages, related_data['pedimento_packages'])
# Crear relaciones uno a muchos
def create_many(model_class, items):
if not items:
return
for item in items:
obj_dict = item.model_dump(exclude_none=True)
obj = model_class(**obj_dict)
obj.pedimento_id = pedimento.id
obj.tenant_id = tenant_id
obj.company_id = company_id
db.add(obj)
create_many(PedimentoTransportCarriers,
related_data['pedimento_transport_carriers'])
create_many(PedimentoGuides, related_data['pedimento_guides'])
create_many(PedimentoContributions, related_data['pedimento_contributions'])
create_many(PedimentoSeals, related_data['pedimento_seals'])
create_many(PedimentoContainers,
related_data['pedimento_containers'])
db.commit()
db.refresh(pedimento)
return pedimento
@@ -323,7 +371,8 @@ class PedimentosService:
'pedimento_rectification_origin', 'pedimento_transport_means',
'pedimento_config_additional', 'pedimento_config_calculations',
'pedimento_config_parameters', 'pedimento_config_surcharges',
'pedimento_config_update_rectification', 'pedimento_config_updates'
'pedimento_config_update_rectification', 'pedimento_config_updates',
'pedimento_packages', 'pedimento_transport_carriers', 'pedimento_guides', 'pedimento_contributions', 'pedimento_seals', 'pedimento_containers'
})
for field, value in update_data.items():
@@ -343,8 +392,13 @@ class PedimentosService:
if not data:
return
existing = service_class.get_by_pedimento_id(
db, pedimento_id, tenant_id, company_id)
existing = None
if service_class:
existing = service_class.get_by_pedimento_id(
db, pedimento_id, tenant_id, company_id)
else:
existing = getattr(pedimento, data_attr, None)
if existing:
# Actualizar existente (excluir pedimento_id, tenant_id, company_id)
for field, value in data.items():
@@ -358,6 +412,28 @@ class PedimentosService:
obj.company_id = company_id
db.add(obj)
def upsert_one_to_many(model_class, data_attr):
full_data = pedimento_data.model_dump()
if data_attr not in full_data:
return
items = full_data[data_attr]
if items is None:
return
# Reemplazar completamente la colección por simplicidad
existing_items = getattr(pedimento, data_attr)
if existing_items:
for item in list(existing_items):
db.delete(item)
for item in items:
obj = model_class(**item)
obj.pedimento_id = pedimento_id
obj.tenant_id = tenant_id
obj.company_id = company_id
db.add(obj)
# Actualizar o crear tablas relacionadas
update_or_create_related(
PedimentoDatesService, PedimentoDates, 'pedimento_dates')
@@ -392,6 +468,15 @@ class PedimentosService:
update_or_create_related(
PedimentoConfigUpdatesService, PedimentoConfigUpdates, 'pedimento_config_updates')
# Manejar nuevas relaciones
update_or_create_related(None, PedimentoPackages, 'pedimento_packages')
upsert_one_to_many(PedimentoTransportCarriers,
'pedimento_transport_carriers')
upsert_one_to_many(PedimentoGuides, 'pedimento_guides')
upsert_one_to_many(PedimentoContributions, 'pedimento_contributions')
upsert_one_to_many(PedimentoSeals, 'pedimento_seals')
upsert_one_to_many(PedimentoContainers, 'pedimento_containers')
db.commit()
db.refresh(pedimento)
return pedimento