Aller au contenu

Format JSON Devis — Deviseur IA EG EVENT

Format obligatoire pour les tools verify_arithmetic, generate_xls, archive_quote.

Structure top-level

{
  "devis": {
    "ref": "DEV-2026-XXX",
    "client": "Nom du client",
    "salon": "Nom du salon",
    "ville": "Paris",
    "surface": 30,
    "type_stand": "menuiserie sur mesure",
    "site_depart": "Villebon-sur-Yvette",
    "date_creation": "2026-05-20",
    "version": 1,
    "tva_pct": 20,
    "auteur_email": "olivier.audemard@gmail.com",
    "postes": [
      { ... },
      { ... }
    ],
    "sous_totaux_par_categorie": {
      "Sol": 1440.00,
      "Menuiserie": 4068.13,
      "Mobilier": 1138.80
    },
    "total_ht": 21044.23,
    "tva_montant": 4208.85,
    "total_ttc": 25253.08,
    "marge_globale": 35.5
  }
}

⚠️ Clé OBLIGATOIRE : postes (pas lignes ni items ni lines)

La liste des lignes de devis s'appelle postes dans devis["postes"]. Tout autre nom de clé sera ignoré silencieusement par les tools (total_ht calculé = 0).

Structure d'un poste (ligne de devis)

{
  "categorie": "Menuiserie",
  "description": "Cloison double face H=2,50m finie",
  "ref_produit": "CLOI-DF-250-ML",
  "fournisseur": "EG EVENT",
  "quantite": 11,
  "unite": "ml",
  "pa_ht": 65.00,
  "pv_ht": 112.00,
  "marge_pct": 72.3,
  "total_pv_ht": 1232.00,
  "source_niveau": "EXACT",
  "source_ref": "[M020] Base de prix/Prix_Menuiserie_Stand.md",
  "note": "",
  "hypothese": "",
  "flag": false
}

Champs obligatoires par poste

  • categorie (string) : Sol, Menuiserie, Mobilier, Électricité, MO, Logistique, Signalétique, etc.
  • description (string)
  • quantite (number)
  • unite (string) : ml, m², u, h, j, forfait, etc.
  • pa_ht (number) : prix achat HT unitaire
  • pv_ht (number) : prix vente HT unitaire
  • marge_pct (number) : marge en % = (pv-pa)/pa × 100 [G003]
  • total_pv_ht (number) : quantite × pv_ht

Champs recommandés

  • ref_produit (string) : code Odoo (10-01-001, 08-01-018, etc.)
  • fournisseur (string) : nom du fournisseur (déclenche [G007] pour les sous-traitants à 0% marge)
  • source_niveau (string) : EXACT | CALCUL | HISTORIQUE | INCONNU
  • source_ref (string) : référence règle + fichier source ([M020] Base de prix/...)
  • flag (boolean) : true si donnée manquante ou anomalie

Source de vérité du parseur

  • mcp-deviseur/tools/arithmetic.py ligne 31 : for i, p in enumerate(devis.get("postes", []))
  • mcp-deviseur/tools/xls_generator.py ligne 88 : postes = sorted(devis.get("postes", []), ...)
  • mcp-deviseur/tools/quote_search.py : utilise frontmatter Obsidian sur les .md, pas ce JSON

Pièges connus

  • "lignes" au lieu de "postes" → total_ht calculé = 0
  • ❌ Quantité en string "30" au lieu de number 30 → ignoré
  • ❌ Oublier total_pv_ht par ligne → ignoré dans les sous-totaux
  • ❌ Mettre marge_pct calculée sur PV au lieu de PA → warning [G003]