from datetime import datetime, timezone from fastapi import HTTPException, status from sqlalchemy.orm import Session from ..accounts.models import Account from ..suppliers.models import Supplier from .dto import ContactCreate, ContactUpdate from .models import Contact def _validate_parent(db: Session, data: dict, tenant_id: int, company_id: int) -> None: """Verifica que el cliente/proveedor referenciado exista en el tenant/company.""" account_id = data.get("account_id") if account_id is not None: exists = ( db.query(Account.id) .filter( Account.id == account_id, Account.tenant_id == tenant_id, Account.company_id == company_id, Account.deleted_at.is_(None), ) .first() ) if not exists: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="El cliente asociado no existe", ) supplier_id = data.get("supplier_id") if supplier_id is not None: exists = ( db.query(Supplier.id) .filter( Supplier.id == supplier_id, Supplier.tenant_id == tenant_id, Supplier.company_id == company_id, Supplier.deleted_at.is_(None), ) .first() ) if not exists: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="El proveedor asociado no existe", ) def get_contacts( db: Session, tenant_id: int, company_id: int, search: str | None = None, account_id: int | None = None, supplier_id: int | None = None, ) -> list[Contact]: query = db.query(Contact).filter( Contact.tenant_id == tenant_id, Contact.company_id == company_id, Contact.deleted_at.is_(None), ) if account_id is not None: query = query.filter(Contact.account_id == account_id) if supplier_id is not None: query = query.filter(Contact.supplier_id == supplier_id) if search: pattern = f"%{search}%" query = query.filter( Contact.first_name.ilike(pattern) | Contact.last_name.ilike(pattern) | Contact.email.ilike(pattern) ) return query.order_by(Contact.first_name.asc()).all() def get_contact(db: Session, contact_id: int, tenant_id: int, company_id: int) -> Contact: contact = ( db.query(Contact) .filter( Contact.id == contact_id, Contact.tenant_id == tenant_id, Contact.company_id == company_id, Contact.deleted_at.is_(None), ) .first() ) if not contact: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Contacto no encontrado") return contact def create_contact(db: Session, payload: ContactCreate, tenant_id: int, company_id: int) -> Contact: data = payload.model_dump() _validate_parent(db, data, tenant_id, company_id) contact = Contact(**data, tenant_id=tenant_id, company_id=company_id) db.add(contact) db.commit() db.refresh(contact) return contact def update_contact( db: Session, contact_id: int, payload: ContactUpdate, tenant_id: int, company_id: int ) -> Contact: contact = get_contact(db, contact_id, tenant_id, company_id) data = payload.model_dump(exclude_unset=True) _validate_parent(db, data, tenant_id, company_id) for field, value in data.items(): setattr(contact, field, value) db.commit() db.refresh(contact) return contact def delete_contact(db: Session, contact_id: int, tenant_id: int, company_id: int) -> None: contact = get_contact(db, contact_id, tenant_id, company_id) contact.deleted_at = datetime.now(timezone.utc) db.commit()