""" annonce_service.py — Logique métier du module Annonces (EXF-01 à EXF-04 du CDC). Validation des champs AVANT d'appeler la couche models/, et journalisation systématique des actions sensibles dans audit_log (Bloc 1 - C10). """ from models import annonce_model from services import audit_service class ValidationError(Exception): """Levée quand les données fournies par l'utilisateur sont invalides.""" TITRE_MAX_LEN = 150 def _validate(titre, contenu): if not titre or not titre.strip(): raise ValidationError("Le titre est obligatoire.") if len(titre) > TITRE_MAX_LEN: raise ValidationError(f"Le titre dépasse {TITRE_MAX_LEN} caractères.") if not contenu or not contenu.strip(): raise ValidationError("Le contenu est obligatoire.") def list_annonces(db): return annonce_model.fetch_all(db) def create_annonce(db, titre, contenu, auteur_sub, epinglee=False, ip=None): _validate(titre, contenu) new_id = annonce_model.insert(db, titre.strip(), contenu.strip(), auteur_sub, epinglee) audit_service.log(db, "CREATE_ANNONCE", f"annonce:{new_id}", "SUCCESS", auteur_sub, ip) return new_id def update_annonce(db, annonce_id, titre, contenu, auteur_sub, epinglee=False, ip=None): _validate(titre, contenu) existing = annonce_model.get(db, annonce_id) if not existing: raise annonce_model.AnnonceNotFoundError(f"Annonce {annonce_id} introuvable") rows = annonce_model.update(db, annonce_id, titre.strip(), contenu.strip(), epinglee) audit_service.log(db, "UPDATE_ANNONCE", f"annonce:{annonce_id}", "SUCCESS", auteur_sub, ip) return rows def delete_annonce(db, annonce_id, auteur_sub, ip=None): existing = annonce_model.get(db, annonce_id) if not existing: raise annonce_model.AnnonceNotFoundError(f"Annonce {annonce_id} introuvable") rows = annonce_model.delete(db, annonce_id) audit_service.log(db, "DELETE_ANNONCE", f"annonce:{annonce_id}", "SUCCESS", auteur_sub, ip) return rows