""" Capa de servicio para lógica de negocio de relación entre partes y países """ import logging from typing import Any, Dict, List, Optional, Tuple from fastapi import HTTPException from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from .dto import PartCountryCreateDTO, PartCountryResponseDTO, PartCountryUpdateDTO from .models import PartCountry logger = logging.getLogger(__name__) class PartCountryService: """Servicio para gestión de relaciones entre partes y países""" @staticmethod def get_all( db: Session, skip: int = 0, limit: int = 50, filters: Optional[Dict[str, Any]] = None, ) -> Tuple[List[PartCountry], int]: """Get all part-country relationships with pagination""" query = db.query(PartCountry) if filters: if filters.get("part_id"): query = query.filter(PartCountry.part_id == filters["part_id"]) if filters.get("country_code"): query = query.filter( PartCountry.country_code.ilike(f"%{filters['country_code']}%") ) if filters.get("preference"): query = query.filter(PartCountry.preference == filters["preference"]) total = query.count() part_countries = query.offset(skip).limit(limit).all() return part_countries, total @staticmethod def get_by_id(db: Session, part_country_id: int) -> Optional[PartCountry]: """Get part-country relationship by ID""" return db.query(PartCountry).filter(PartCountry.id == part_country_id).first() @staticmethod def get_by_part_id(db: Session, part_id: int) -> List[PartCountry]: """Get all countries for a specific part""" return db.query(PartCountry).filter(PartCountry.part_id == part_id).all() @staticmethod def get_by_part_and_country(db: Session, part_id: int, country_code: str) -> Optional[PartCountry]: """Get specific part-country relationship""" return db.query(PartCountry).filter( PartCountry.part_id == part_id, PartCountry.country_code == country_code ).first() @staticmethod def create(db: Session, part_country_data: PartCountryCreateDTO) -> PartCountry: """Create a new part-country relationship""" try: db_part_country = PartCountry( **part_country_data.model_dump(exclude_unset=True) ) db.add(db_part_country) db.commit() db.refresh(db_part_country) return db_part_country except IntegrityError as e: db.rollback() logger.error(f"IntegrityError creating part-country relationship: {str(e)}") raise HTTPException( status_code=400, detail="Relationship already exists or invalid foreign key", ) except Exception as e: db.rollback() logger.error(f"Error creating part-country relationship: {str(e)}") raise HTTPException( status_code=500, detail=f"Error creating relationship: {str(e)}", ) @staticmethod def update( db: Session, part_country_id: int, part_country_data: PartCountryUpdateDTO ) -> Optional[PartCountry]: """Update part-country relationship""" try: db_part_country = db.query(PartCountry).filter( PartCountry.id == part_country_id ).first() if not db_part_country: return None update_data = part_country_data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(db_part_country, field, value) db.add(db_part_country) db.commit() db.refresh(db_part_country) return db_part_country except IntegrityError as e: db.rollback() logger.error(f"IntegrityError updating part-country relationship: {str(e)}") raise HTTPException( status_code=400, detail="Cannot update: constraint violation", ) except Exception as e: db.rollback() logger.error(f"Error updating part-country relationship: {str(e)}") raise HTTPException( status_code=500, detail=f"Error updating relationship: {str(e)}", ) @staticmethod def delete(db: Session, part_country_id: int) -> bool: """Delete part-country relationship""" try: db_part_country = db.query(PartCountry).filter( PartCountry.id == part_country_id ).first() if not db_part_country: return False db.delete(db_part_country) db.commit() return True except Exception as e: db.rollback() logger.error(f"Error deleting part-country relationship: {str(e)}") raise HTTPException( status_code=500, detail=f"Error deleting relationship: {str(e)}", ) @staticmethod def bulk_create(db: Session, part_id: int, countries_data: List[PartCountryCreateDTO]) -> List[PartCountry]: """Create multiple part-country relationships for a part""" try: # Delete existing relationships for this part db.query(PartCountry).filter(PartCountry.part_id == part_id).delete() db.commit() # Create new relationships db_part_countries = [] for country_data in countries_data: country_data.part_id = part_id db_part_country = PartCountry( **country_data.model_dump(exclude_unset=True) ) db_part_countries.append(db_part_country) db.add_all(db_part_countries) db.commit() for pc in db_part_countries: db.refresh(pc) return db_part_countries except Exception as e: db.rollback() logger.error(f"Error bulk creating part-country relationships: {str(e)}") raise HTTPException( status_code=500, detail=f"Error creating relationships: {str(e)}", )