Détail exhaustif, chiffre par chiffre, graphique par graphique : la formule exacte, la
période/le périmètre pris en compte, et l'endpoint qui la calcule. Toutes les statistiques de ce
module lisent une seule et même table pivot : stocks_mouvement_officiel.
Chaque vente ou achat de carburant/produit/service finit par une ligne dans
stocks_mouvement_officiel. Colonnes utilisées par tous les calculs de cette page :
journee (date), id_produit, entre (quantité achetée),
sortie (quantité vendue), prix (prix unitaire au moment du mouvement),
tva, source.
| Origine | Quand la ligne est créée | source |
|---|---|---|
| Ticket Point de Vente (ComptePv) | À chaque produit/service ajouté sur un ticket | Ticket |
| Compte PS (ancien circuit point de service) | À la clôture du compte, en un seul lot regroupant produits et services de toute la session | PS |
| Vente directe ("Transfert Bon") | À la clôture d'un Bon de Livraison Achat transformé en Bon client | AlimentationBL |
| Achat fournisseur (Bon de Livraison) | À la clôture du Bon de Livraison | Alimentation |
Toutes les lignes avec source='Verification' (écarts de stock constatés) sont
exclues de tous les calculs Vente/Achat de cette page (elles ne représentent ni une
vente ni un achat réel).
Endpoint : /StatistiqueGraphique/evolution avec type_vente=tous → statistique_annee_optimisee('tous', année)
| Chiffre affiché | Formule exacte |
|---|---|
| Courbe Vente (par mois, année choisie) | SUM(sortie * prix) — aucun filtre type_vente (tous produits confondus), GROUP BY MONTH(journee), YEAR(journee) = année |
| Courbe Achat (par mois, année choisie) | SUM(entre * prix) — hors taxe (pas de ×(1+tva/100)), même filtre/regroupement |
Comme ce total ne filtre par aucun type_vente, il est mathématiquement égal à
(total Carburant hors Adblue) + (total Lubrifiant & Service avec Adblue) — voir §11 pour le
détail du partage Carburant/Adblue.
Endpoint : /StatistiqueGraphique/statistique — filtres Du/Au/Fixateur/Taxe
Périmètre : uniquement stocks_produits.type_vente='carburant' AND tva≠20 (l'Adblue,
seul produit carburant à tva=20, est exclu d'ici — voir §11). Le sélecteur
Taxe choisit un diviseur appliqué à la toute fin de chaque calcul monétaire :
diviseur = 1 si TTC, diviseur = 1,10 si HT (10% étant le taux de TVA réel
du carburant).
montant_carburant = SUM(sortie × prix) | qte_carburant = SUM(sortie)La marge n'est pas un simple "vente − achat de la période" : elle valorise la quantité vendue à son coût moyen pondéré réel (CUMP), qui remonte jusqu'au stock initial de l'application si nécessaire. Calcul en 2 temps, par carburant :
initial())entre × prix × (1+tva/100).entre et Σ entre×prix×(1+tva/100) sur cet intervalle.initial() : montant = ce coût, qte = la quantité de l'étape 6.statistique())entre et Σ entre×prix×(1+tva/100) sur cet intervalle (fonction achat_periode()).À retenir : si le Fixateur est très ancien, le calcul remonte potentiellement à l'historique complet du produit (tous les achats jamais enregistrés avant cette date) pour obtenir un CUMP de départ fiable — un Fixateur mal choisi peut donc rendre le calcul plus lourd, mais n'affecte la marge que via le CUMP de départ, pas la vente de la période.
en_stock = stock initial application + Σ(entre − sortie) sur toutes les lignes AVANT la date (Au + 1 jour)valeur_carburant = (en_stock × PMP final de l'étape B.2) / diviseur| Graphique | Formule |
|---|---|
| Chiffre d'Affaires par Carburant (barres) | 1 barre par carburant = montant_carburant / diviseur (§3.1, avant sommation) |
| PMV vs PMP par Carburant (barres, 2 séries) |
PMV (Prix Moyen de Vente constaté) = montant_carburant / qte_carburant (÷ diviseur)PMP (CUMP) = PMP final de l'étape B.2 (÷ diviseur) |
| Remplissage des Citernes (barres horizontales, %) | % = ROUND(en_stock / volume_max × 100), où en_stock est valorisé à la date (Au + 1 jour) comme en §3.3, et volume_max = SUM(carburant_citerne.volume) pour les citernes de ce carburant |
| Répartition Encaissement (anneau, 5 catégories) | Voir tableau détaillé ci-dessous — chaque catégorie = SUM(carburant_compte_bon.montant) sur les comptes carburant clôturés dans [Du, Au] |
| Catégorie d'encaissement | Filtre exact sur carburant_compte_bon |
|---|---|
| Crédit Client | id_type = 1 |
| Espèce | id_type = 6 |
| CMI | id_type = 2, lié à une ligne carte_ticket dont le type de carte a id_fournisseur = 0 (carte bancaire classique) |
| TOMCARD | id_type = 2, lié à une ligne carte_ticket dont le type de carte a id_fournisseur ≠ 0 (carte carburant fournisseur) |
| Chèque | id_type = 5, lié à une ligne coffre_piece avec id_mode = 1 |
| LCN | id_type = 5, lié à une ligne coffre_piece avec id_mode = 2 |
| Chèque/LCN (affiché) | Chèque + LCN additionnés |
| Total | Somme des 5 catégories |
Endpoint : /StatistiqueGraphique/evolution avec type_vente=carburant → statistique_annee_optimisee('carburant', année)
Filtre unique : l'année (pas de Du/Au/Fixateur/Taxe ici). Une seule courbe à 2 axes (CA à gauche, Quantité à droite), un point par mois.
| Chiffre | Formule |
|---|---|
| Chiffre d'Affaires (par mois) | SUM(sortie × prix), produits type_vente='carburant' AND tva≠20 (Adblue exclu), YEAR(journee)=année, GROUP BY MONTH(journee) |
| Quantité (par mois) | SUM(sortie), mêmes filtres |
Ces montants sont toujours TTC bruts (prix directement, sans
aucun diviseur HT/TVA) — contrairement à l'onglet Général (§3) où le sélecteur Taxe s'applique.
Pour l'année en cours, les mois futurs (et le mois en cours, toujours incomplet) sont
automatiquement retirés du graphique.
Endpoints : /StatistiqueGraphique/charte_comparaison (courbes + tableau Achat/Vente) et /StatistiqueGraphique/charte_encaissement (tableau Encaissement)
Filtres : une ou plusieurs années, et une plage Mois du → Mois au (appliquée à chaque année sélectionnée). Bouton Montants/Quantités = bascule d'affichage seulement (aucun recalcul serveur).
| Élément | Formule |
|---|---|
| Courbes "Vente {année}" / "Achat {année}" | Mêmes valeurs mensuelles que l'onglet Évolution (§4), simplement tronquées à la plage Mois du→Au et affichées pour chaque année choisie sur le même graphique |
| Tableau Achat / Vente — total par année | Σ des mois de la plage Mois du→Au sélectionnée (Vente = Σ CA mensuel ; Achat = Σ Achat mensuel HT, voir §10) |
| Badge % d'évolution | (valeur_année − valeur_année_précédente) / |valeur_année_précédente| × 100 — "précédente" = l'année juste avant dans la LISTE TRIÉE choisie (pas forcément l'année civile −1). À partir de la 3ᵉ année de la liste, un 2ᵉ badge compare aussi à la toute première année choisie |
| Tableau Encaissement — total par année | Mêmes 5 catégories que §3.4, mais encaissement_periode(année, mois_du, mois_au) : YEAR(journee)=année AND MONTH(journee) BETWEEN mois_du AND mois_au sur carburant_compte_bon |
Endpoint : /StatistiqueGraphique/statistique_ps → Statistiques::par_produit('ps', Du, Au)
Périmètre : type_vente IN ('produit','service') OU
(type_vente='carburant' AND tva=20, c.-à-d. l'Adblue — voir §11). Filtres : Du/Au
seulement.
Le sélecteur Taxe (TTC/HT) visible sur cet onglet n'a aucun effet : le paramètre n'est jamais lu côté serveur pour ce calcul (contrairement à l'onglet Carburant, §3). Tous les chiffres ci-dessous sont donc toujours dans l'unité brute stockée en base (TTC).
| Chiffre affiché | Formule exacte |
|---|---|
| CA Vente | Σ SUM(sortie × prix) sur tous les produits/services du périmètre, [Du, Au], toutes sources confondues (Ticket/PS/AlimentationBL) |
| CA Achat | Σ SUM(entre × prix × (1+tva/100)) — uniquement source='Alimentation', et uniquement les lignes type_vente='produit' ou Adblue (un service n'a jamais d'achat, il n'a pas de prix d'achat) |
| Marge | CA Vente − CA Achat — soustraction simple, pas de calcul PMP pondéré comme pour le Carburant (§3.2) : c'est un vrai delta vente/achat sur la période, pas une marge sur coût moyen |
| Quantité Vendue | Σ SUM(sortie) sur tout le périmètre |
| Chiffre d'Affaires par Produit/Service (barres) | Les 10 produits/services au CA le plus élevé, chacun affiché individuellement ; tout le reste est regroupé dans une barre "Autres" (somme du CA et de la quantité restants) |
Endpoint : /StatistiqueGraphique/evolution avec type_vente=ps → statistique_annee_optimisee('ps', année)
Même principe que l'Évolution Carburant (§4), mais périmètre = type_vente IN
('produit','service') OU Adblue. Chiffre d'Affaires et Quantité par mois
pour l'année choisie, mêmes formules SUM(sortie×prix) / SUM(sortie).
Endpoint : /StatistiqueGraphique/charte_comparaison avec type_vente=ps
Identique au Carburant (§5) pour les courbes multi-années et le tableau Achat/Vente + badges
d'évolution. Pas de tableau Encaissement ici : le circuit d'encaissement
(carburant_compte_bon) est propre au module Carburant et lié à une session de caisse,
pas à une ligne produit — un même paiement peut mélanger carburant/lubrifiant/service, donc une
ventilation par mode de paiement au niveau produit n'aurait pas de sens.
L'Adblue est vendu au pistolet, comme du carburant (même circuit
index/citerne), mais c'est économiquement un produit soumis à la TVA normale de
20% — alors que le vrai carburant (gasoil, SP95...) est à 10%. En base,
stocks_produits a une ligne type_vente='carburant' pour l'Adblue mais
avec tva=20, contre tva=10 pour les carburants réels.
Règle appliquée partout dans ce module : toute ligne
type_vente='carburant' AND tva=20 est traitée comme un "produit vendu par index" —
exclue du total Carburant (§3, §4, §5) et incluse dans le total
Lubrifiant & Service (§6, §7, §8), donc aussi dans le Général (§2, somme des deux). Règle
générique basée sur le taux de TVA (pas sur le nom du produit) : un futur produit configuré de la
même façon serait automatiquement classé pareil, sans modification de code.
| Onglet / sous-onglet | Le sélecteur Taxe a-t-il un effet ? | Convention Achat |
|---|---|---|
| Général | Pas de sélecteur | HT (entre×prix, sans TVA) |
| Carburant → Général | Oui (diviseur 1 ou 1,10 sur CA/Marge/Valeur Stock/PMV/PMP) | TTC (entre×prix×(1+tva/100)) |
| Carburant → Évolution / Comparaison | Pas de sélecteur | HT (entre×prix, sans TVA) |
| Lubrifiant & Service → Général | Sélecteur présent mais inactif (voir §6) | TTC (entre×prix×(1+tva/100)) |
| Lubrifiant & Service → Évolution / Comparaison | Pas de sélecteur | HT (entre×prix, sans TVA) |
Ces conventions différentes entre onglets sont un comportement déjà en place (non modifié) — à garder en tête si vous comparez un montant "Achat" d'un onglet à un autre : ils ne sont pas toujours calculés sur la même base HT/TTC.
Un bug a été trouvé et corrigé : la vente directe "Transfert Bon" (achat transformé directement
en vente client, sans passer par un ticket ni une clôture de compte) créait bien son mouvement de
stock, mais ne l'enregistrait jamais dans stocks_mouvement_officiel —
ces ventes étaient donc invisibles dans toutes les statistiques ci-dessus. Corrigé pour les
nouvelles clôtures, et rattrapé pour l'historique (migration de base de données rejouée sur toutes
les bases).
Cette page est un complément à
SKILL_MODULE_VENTE.md (journal détaillé des chantiers de développement) — elle explique
le résultat final, pas l'historique des décisions. Fichiers sources de ces calculs :
app/models/home/Statistiques.php et
app/controllers/statistique/StatistiqueGraphiqueController.php.