Files
plantillas-proyectos/backend/api/v1/modules/a76/pedmientos/services/pedimentos.py
acazares ba40123333 feat: Enhance Pedimentos CRUD operations with related data handling
- Updated PedimentosService to create and update related tables for Pedimentos.
- Added company_id filtering in queries for Pedimentos.
- Improved error handling and logging during creation and update processes.
- Refactored router tags for consistency and clarity.
- Adjusted API endpoints for customs brokers to include company_id in requests.
- Enhanced company selection logic in various components to prioritize active company.
- Implemented event listeners for company changes to reload data dynamically.
- Updated frontend components to handle loading states and errors more effectively.
- Ensured all relevant routes and API calls are aligned with the new company context.
2025-11-14 18:14:33 -06:00

320 lines
15 KiB
Python

"""
Service layer for Pedimentos CRUD operations
"""
import logging
from typing import Any, Dict, List, Optional
from sqlalchemy import desc
from sqlalchemy.orm import Session
from ..dtos.pedimentos import PedimentosCreate, PedimentosUpdate
from .pedimento_config_additional import PedimentoConfigAdditionalService
from .pedimento_config_calculations import PedimentoConfigCalculationsService
from .pedimento_config_parameters import PedimentoConfigParametersService
from .pedimento_config_surcharges import PedimentoConfigSurchargesService
from .pedimento_config_update_rectification import PedimentoConfigUpdateRectificationService
from .pedimento_config_updates import PedimentoConfigUpdatesService
from .pedimento_customs_offices import PedimentoCustomsOfficesService
from .pedimento_dates import PedimentoDatesService
from .pedimento_decrementables import PedimentoDecrementablesService
from .pedimento_incrementables import PedimentoIncrementablesService
from .pedimento_indexes import PedimentoIndexesService
from .pedimento_payments import PedimentoPaymentsService
from .pedimento_rectification_destination import PedimentoRectificationDestinationService
from .pedimento_rectification_origin import PedimentoRectificationOriginService
from .pedimento_transport_means import PedimentoTransportMeansService
from .pedimento_validation import PedimentoValidationService
# Crear tablas relacionadas si existen datos
from ..models.pedimentos import Pedimentos
from ..models.pedimento_dates import PedimentoDates
from ..models.pedimento_decrementables import PedimentoDecrementables
from ..models.pedimento_incrementables import PedimentoIncrementables
from ..models.pedimento_indexes import PedimentoIndexes
from ..models.pedimento_validation import PedimentoValidation
from ..models.pedimento_customs_offices import PedimentoCustomsOffices
from ..models.pedimento_payments import PedimentoPayments
from ..models.pedimento_rectification_destination import PedimentoRectificationDestination
from ..models.pedimento_rectification_origin import PedimentoRectificationOrigin
from ..models.pedimento_transport_means import PedimentoTransportMeans
from ..models.pedimento_config_additional import PedimentoConfigAdditional
from ..models.pedimento_config_calculations import PedimentoConfigCalculations
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
logger = logging.getLogger(__name__)
class PedimentosService:
"""Service class for Pedimentos business logic"""
@staticmethod
def get_all(
db: Session,
tenant_id: int,
company_id: int,
skip: int = 0,
limit: int = 100,
filters: Optional[Dict[str, Any]] = None,
) -> tuple[List[Pedimentos], int]:
"""
Get all pedimentos for a tenant with pagination and filters
Args:
db: Database session
tenant_id: Tenant ID
skip: Number of records to skip
limit: Maximum number of records to return
filters: Optional filters dict
Returns:
Tuple of (list of pedimentos, total count)
"""
query = db.query(Pedimentos).filter(Pedimentos.tenant_id == tenant_id, Pedimentos.company_id == company_id)
if filters:
if filters.get("status"):
query = query.filter(Pedimentos.status == filters["status"])
if filters.get("client_id"):
query = query.filter(Pedimentos.client_id == filters["client_id"])
if filters.get("year"):
query = query.filter(Pedimentos.year == filters["year"])
total = query.count()
items = (
query.order_by(desc(Pedimentos.created_at)).offset(skip).limit(limit).all()
)
return items, total
@staticmethod
def get_by_id(
db: Session, pedimento_id: int, tenant_id: int, company_id: int = None
) -> Optional[Pedimentos]:
"""
Get a pedimento by ID
Args:
db: Database session
pedimento_id: Pedimento ID
tenant_id: Tenant ID
company_id: Company ID (optional for backwards compatibility)
Returns:
Pedimento or None if not found
"""
query = db.query(Pedimentos).filter(
Pedimentos.id == pedimento_id, Pedimentos.tenant_id == tenant_id, Pedimentos.company_id == company_id
)
if company_id is not None:
query = query.filter(Pedimentos.company_id == company_id)
return query.first()
@staticmethod
def create(
db: Session, pedimento_data: PedimentosCreate, tenant_id: int, company_id: int
) -> Pedimentos:
"""
Create a new pedimento with related tables
Args:
db: Database session
pedimento_data: Pedimento creation data
tenant_id: Tenant ID
company_id: Company ID
Returns:
Created pedimento
"""
try:
# Extraer datos de tablas relacionadas
related_data = {
'pedimento_dates': pedimento_data.pedimento_dates,
'pedimento_decrementables': pedimento_data.pedimento_decrementables,
'pedimento_incrementables': pedimento_data.pedimento_incrementables,
'pedimento_indexes': pedimento_data.pedimento_indexes,
'pedimento_validation': pedimento_data.pedimento_validation,
'pedimento_customs_offices': pedimento_data.pedimento_customs_offices,
'pedimento_payments': pedimento_data.pedimento_payments,
'pedimento_rectification_destination': pedimento_data.pedimento_rectification_destination,
'pedimento_rectification_origin': pedimento_data.pedimento_rectification_origin,
'pedimento_transport_means': pedimento_data.pedimento_transport_means,
'pedimento_config_additional': pedimento_data.pedimento_config_additional,
'pedimento_config_calculations': pedimento_data.pedimento_config_calculations,
'pedimento_config_parameters': pedimento_data.pedimento_config_parameters,
'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,
}
# Crear pedimento principal (excluyendo relaciones)
pedimento_dict = pedimento_data.model_dump(exclude={
'pedimento_dates', 'pedimento_decrementables', 'pedimento_incrementables',
'pedimento_indexes', 'pedimento_validation', 'pedimento_customs_offices',
'pedimento_payments', 'pedimento_rectification_destination',
'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 = Pedimentos(**pedimento_dict)
pedimento.tenant_id = tenant_id
pedimento.company_id = company_id
db.add(pedimento)
db.flush() # Flush para obtener el ID sin commit
# Helper function para crear objetos relacionados
def create_related(model_class, data):
if data:
obj_dict = data.model_dump()
obj = model_class(**obj_dict)
obj.pedimento_id = pedimento.id
obj.tenant_id = tenant_id
obj.company_id = company_id
db.add(obj)
create_related(PedimentoDates, related_data['pedimento_dates'])
create_related(PedimentoDecrementables, related_data['pedimento_decrementables'])
create_related(PedimentoIncrementables, related_data['pedimento_incrementables'])
create_related(PedimentoIndexes, related_data['pedimento_indexes'])
create_related(PedimentoValidation, related_data['pedimento_validation'])
create_related(PedimentoCustomsOffices, related_data['pedimento_customs_offices'])
create_related(PedimentoPayments, related_data['pedimento_payments'])
create_related(PedimentoRectificationDestination, related_data['pedimento_rectification_destination'])
create_related(PedimentoRectificationOrigin, related_data['pedimento_rectification_origin'])
create_related(PedimentoTransportMeans, related_data['pedimento_transport_means'])
create_related(PedimentoConfigAdditional, related_data['pedimento_config_additional'])
create_related(PedimentoConfigCalculations, related_data['pedimento_config_calculations'])
create_related(PedimentoConfigParameters, related_data['pedimento_config_parameters'])
create_related(PedimentoConfigSurcharges, related_data['pedimento_config_surcharges'])
create_related(PedimentoConfigUpdateRectification, related_data['pedimento_config_update_rectification'])
create_related(PedimentoConfigUpdates, related_data['pedimento_config_updates'])
db.commit()
db.refresh(pedimento)
return pedimento
except Exception as e:
db.rollback()
logger.error(f"Error creating pedimento with related data: {e}")
raise
@staticmethod
def update(
db: Session, pedimento_id: int, tenant_id: int, pedimento_data: PedimentosUpdate, company_id: int = None
) -> Optional[Pedimentos]:
"""
Update a pedimento and its related tables
Args:
db: Database session
pedimento_id: Pedimento ID
tenant_id: Tenant ID
pedimento_data: Updated data
company_id: Company ID (optional for backwards compatibility)
Returns:
Updated pedimento or None if not found
"""
pedimento = PedimentosService.get_by_id(db, pedimento_id, tenant_id, company_id)
if not pedimento:
return None
try:
# Actualizar campos principales del pedimento
update_data = pedimento_data.model_dump(exclude_unset=True, exclude={
'pedimento_dates', 'pedimento_decrementables', 'pedimento_incrementables',
'pedimento_indexes', 'pedimento_validation', 'pedimento_customs_offices',
'pedimento_payments', 'pedimento_rectification_destination',
'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'
})
for field, value in update_data.items():
setattr(pedimento, field, value)
db.flush()
# Helper function para actualizar o crear objetos relacionados
def update_or_create_related(service_class, model_class, data_attr):
if not hasattr(pedimento_data, data_attr):
return
data = getattr(pedimento_data, data_attr)
if not data:
return
existing = service_class.get_by_pedimento_id(db, pedimento_id, tenant_id)
if existing:
# Actualizar existente
update_dict = data.model_dump(exclude_unset=True)
for field, value in update_dict.items():
setattr(existing, field, value)
else:
# Crear nuevo
obj_dict = data.model_dump()
obj = model_class(**obj_dict)
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')
update_or_create_related(PedimentoDecrementablesService, PedimentoDecrementables, 'pedimento_decrementables')
update_or_create_related(PedimentoIncrementablesService, PedimentoIncrementables, 'pedimento_incrementables')
update_or_create_related(PedimentoIndexesService, PedimentoIndexes, 'pedimento_indexes')
update_or_create_related(PedimentoValidationService, PedimentoValidation, 'pedimento_validation')
update_or_create_related(PedimentoCustomsOfficesService, PedimentoCustomsOffices, 'pedimento_customs_offices')
update_or_create_related(PedimentoPaymentsService, PedimentoPayments, 'pedimento_payments')
update_or_create_related(PedimentoRectificationDestinationService, PedimentoRectificationDestination, 'pedimento_rectification_destination')
update_or_create_related(PedimentoRectificationOriginService, PedimentoRectificationOrigin, 'pedimento_rectification_origin')
update_or_create_related(PedimentoTransportMeansService, PedimentoTransportMeans, 'pedimento_transport_means')
update_or_create_related(PedimentoConfigAdditionalService, PedimentoConfigAdditional, 'pedimento_config_additional')
update_or_create_related(PedimentoConfigCalculationsService, PedimentoConfigCalculations, 'pedimento_config_calculations')
update_or_create_related(PedimentoConfigParametersService, PedimentoConfigParameters, 'pedimento_config_parameters')
update_or_create_related(PedimentoConfigSurchargesService, PedimentoConfigSurcharges, 'pedimento_config_surcharges')
update_or_create_related(PedimentoConfigUpdateRectificationService, PedimentoConfigUpdateRectification, 'pedimento_config_update_rectification')
update_or_create_related(PedimentoConfigUpdatesService, PedimentoConfigUpdates, 'pedimento_config_updates')
db.commit()
db.refresh(pedimento)
return pedimento
except Exception as e:
db.rollback()
logger.error(f"Error updating pedimento with related data: {e}")
raise
@staticmethod
def delete(db: Session, pedimento_id: int, tenant_id: int, company_id: int = None) -> bool:
"""
Delete a pedimento
Args:
db: Database session
pedimento_id: Pedimento ID
tenant_id: Tenant ID
company_id: Company ID (optional for backwards compatibility)
Returns:
True if deleted, False if not found
"""
pedimento = PedimentosService.get_by_id(db, pedimento_id, tenant_id, company_id)
if not pedimento:
return False
db.delete(pedimento)
db.commit()
return True