"""Helpers partagés par les routers CRUD.""" import uuid from collections.abc import Iterable from fastapi import HTTPException from sqlalchemy import delete from sqlmodel import Session, select from app.models import Skill def owned_or_404(instance, edition_id: uuid.UUID): """404 si l'instance est absente ou rattachée à une autre édition.""" if instance is None or instance.edition_id != edition_id: raise HTTPException(status_code=404, detail={"code": "error.not_found"}) return instance def resolve_skills( session: Session, edition_id: uuid.UUID, codes: Iterable[str] ) -> list[Skill]: """Récupère ou crée les compétences de l'édition pour les codes donnés.""" existing = { s.code: s for s in session.exec( select(Skill).where(Skill.edition_id == edition_id) ) } resolved: list[Skill] = [] seen: set[str] = set() for raw in codes: code = raw.strip() if not code or code in seen: continue seen.add(code) skill = existing.get(code) if skill is None: skill = Skill(edition_id=edition_id, code=code, label=code) session.add(skill) session.flush() existing[code] = skill resolved.append(skill) return resolved def replace_links( session: Session, link_model, *, filter_column, filter_value, pairs ) -> None: """Remplace toutes les lignes d'une table d'association pour une clé.""" session.execute( delete(link_model).where(filter_column == filter_value) ) for row in pairs: session.add(link_model(**row))