# Avis de sanction & retenue L'application génère des PDFs officiels d'avis de sanction et d'avis de retenue à partir des templates AcroForm fournis (`data/templates/GF_FO_Avis_de_sanction.pdf` et `GF_FO_Avis_de_retenue.pdf`). Les champs du formulaire restent éditables après téléchargement. ## Où créer un avis Bouton **« Créer un avis de retenue »** (orange) ou **« Créer un avis de sanction »** (rouge) : - Sur `/fiche` (Apprentis) — dans le bandeau d'actions sous les KPIs - Sur `/classe` (Classes) — sur chaque carte apprenti, même bandeau Cliquer ouvre une modale dédiée pré-remplie avec l'apprenti sélectionné. ## Modale Avis de sanction Champs : - **Apprenti** (verrouillé, pré-rempli) - **Texte de description** : pré-rempli depuis `settings.texte_sanction` (configurable en /params) - **Chef de section** : pré-rempli depuis `settings.chef_section` - **Préfixe utilisateur** : `() ` est ajouté en début de la remarque enregistrée en notice (traçabilité) 3 actions : - **Télécharger uniquement** — génère le PDF + crée la notice Escada en `pending` - **Envoyer par email** — choix destinataire (apprenti / formateur / autre adresse libre) - **Détecte les notices doublons** : si une notice du même type a déjà été créée aujourd'hui, l'app le signale avec un toast et propose « Créer quand même » Filtre : **uniquement les classes EM** côté UI (les classes DUAL ne peuvent pas générer d'avis de sanction). ## Modale Avis de retenue Champs : - **Apprenti** - **Profession** (auto-calculée depuis le préfixe de classe via `prof_mapping` configuré en /params) - **Date de retenue** (date d'envoi) - **Date du problème** (date à laquelle l'incident s'est produit) - **Case cochée** : Devoir non rendu / Comportement / Retard - **Branche** (uniquement si « Devoir non rendu ») - **Remarque libre** (préfixée par `() `) - **Vos initiales** (champ `Profs` du template) Le template a un champ `Date` partagé entre 3 lignes ; le code [src/retenue_pdf.py:_split_date_field](src/retenue_pdf.py) sépare les widgets pour ne remplir que la date correspondant à la case cochée. ## Destinataire de l'avis (adresse imprimée sur le PDF) Depuis mai 2026, l'adresse de l'**entreprise n'est plus utilisée**. Logique unifiée (`_destinataire(apprenti, fiche)` dans les deux modules PDF) : | Statut apprenti | Destinataire (NomParents / NomEntreprise + Adresse + NPA-Ville) | |---------------------------|------------------------------------------------------------------| | Mineur (`majeur=False`) | Représentant légal (`resp_legal_*`) | | Majeur (`majeur=True`) | Apprenti lui-même (`fiche.adresse/code_postal/localite`) | | Inconnu / pas de fiche | Apprenti lui-même | > Pré-requis : la sync Escada avec option « Données apprentis » doit avoir été lancée pour que `ApprentiFiche.majeur` + `resp_legal_*` soient remplis. ## Notice Escada associée Chaque avis téléchargé crée une `Notice` (table locale) avec : - `source` = `"sanction"` ou `"retenue"` - `status` = `"pending"` - `titre` = « Avis de sanction » / « Est arrivé en retard aux cours » / etc. - `remarque` = `() ` — le préfixe sert d'identification de l'auteur en attendant un compte Escada par utilisateur - `date_event` = aujourd'hui Ces notices sont poussées vers Escada par `scripts/push_notices.py` (cf. [Push vers Escada](#)). ## Configuration des défauts `/params → Avis de sanction` : - Texte de description par défaut - Chef de section (CS) par défaut `/params → Correspondances classe → profession` : - Mapping `préfixe de classe → profession` utilisé sur les avis de retenue. Ex : `AUTOMAT` → `Automaticien CFC`. - Liste des classes « orphelines » (sans mapping) en chips jaunes — clic pour pré-remplir le formulaire. - Bouton « Appliquer aux fiches existantes » : recalcule `ApprentiFiche.profession` pour tous les apprentis selon le mapping actuel. ## Audit ``` [notice] prof.demo : création (sanction) pour Dupont Marc (1EM1) [notice] prof.demo : notice doublon évitée pour Dupont Marc (existante : Avis de sanction — créée le 12.05.2026 10:23) [notice] prof.demo : création (retenue) pour Martin Léa (2EM2) — case=retard ```