Module 3 · Scripts et fichiers de référenceEnviron 1 min
Le script de vérification
Le script tient en une cinquantaine de lignes et n’utilise que la bibliothèque standard de Python : il tourne partout, sans installation. Enregistrez-le dans controle-factures/scripts/verifier_factures.py.
python
"""Contrôle factures.csv (séparateur ;) et affiche les anomalies, facture par facture."""
import csv
import re
import sys
from datetime import date
from decimal import Decimal, InvalidOperation
# Taux normal de TVA au Maroc. Ajoutez les taux réduits qui concernent vos clients,
# selon la loi de finances en vigueur.
TAUX_TVA = {Decimal("0.20")}
# Un centime : l'écart d'arrondi admis entre HT + TVA et TTC.
TOLERANCE = Decimal("0.01")
COLONNES = ["numero", "fournisseur", "ice", "date", "ht", "tva", "ttc"]
def anomalies(facture: dict) -> list[str]:
def valeur(colonne: str) -> str:
return (facture.get(colonne) or "").strip()
erreurs = []
if not re.fullmatch(r"\d{15}", valeur("ice")):
erreurs.append(f"ICE « {valeur('ice')} » : 15 chiffres attendus")
try:
date.fromisoformat(valeur("date"))
except ValueError:
erreurs.append(f"date « {valeur('date')} » : format AAAA-MM-JJ attendu")
try:
ht, tva, ttc = (Decimal(valeur(c)) for c in ("ht", "tva", "ttc"))
except InvalidOperation:
return erreurs + ["montant illisible : point décimal, sans espace ni devise"]
if abs(ht + tva - ttc) > TOLERANCE:
erreurs.append(f"HT + TVA = {ht + tva} mais TTC = {ttc}")
if ht > 0 and (tva / ht).quantize(Decimal("0.01")) not in TAUX_TVA:
erreurs.append(f"taux de TVA de {tva / ht:.2%}, absent de TAUX_TVA")
return erreurs
def main() -> None:
if len(sys.argv) != 2:
sys.exit("Usage : python3 verifier_factures.py factures.csv")
try:
with open(sys.argv[1], newline="", encoding="utf-8-sig") as f:
factures = list(csv.DictReader(f, delimiter=";"))
except FileNotFoundError:
sys.exit(f"Fichier introuvable : {sys.argv[1]}")
if not factures or set(COLONNES) - set(factures[0]):
sys.exit(f"Colonnes attendues, dans cet ordre : {';'.join(COLONNES)}")
total = 0
for facture in factures:
for erreur in anomalies(facture):
total += 1
print(f"Facture {facture.get('numero')} : {erreur}")
print(f"Factures contrôlées : {len(factures)}. Anomalies : {total}.")
if __name__ == "__main__":
main()Voici ce qu’il affiche sur un fichier d’essai de cinq factures :
Texte
$ python3 scripts/verifier_factures.py factures.csv
Facture F-0412 : HT + TVA = 12000.00 mais TTC = 12400.00
Facture F-0419 : ICE « 00152874600003 » : 15 chiffres attendus
Facture F-0420 : date « 14/10/2026 » : format AAAA-MM-JJ attendu
Facture F-0420 : taux de TVA de 10.00%, absent de TAUX_TVA
Facture F-0421 : montant illisible : point décimal, sans espace ni devise
Factures contrôlées : 5. Anomalies : 5.Chaque message dit quelle facture regarder et pourquoi. Un message précis permet à Claude de se corriger seul ; un simple « erreur » le laisse deviner. Les constantes sont commentées : on sait pourquoi la tolérance vaut un centime.
Planifier, valider, exécuterAppliquez le même principe avant toute opération en masse. Si Yassine fait mettre à jour 300 fiches produit, sa Skill demande d’abord un fichier
modifications.json, le fait vérifier par un script, et n’applique les changements qu’ensuite. Les erreurs se corrigent sur le plan, pas sur la boutique.