Aller au contenu

Formats d'export et analyses - PT2QE

Organisation des fichiers générés

Structure des dossiers de sortie

outputs/
├── run_YYYYMMDD_HHMMSS/              # Exécution initiale (Option 1)
│   ├── recommendations_detail.csv
│   ├── statistics_by_dimension.csv
│   ├── impact_analysis.csv
│   ├── price_increase_distribution.csv
│   ├── decision_path_analysis.csv
│   ├── capping_distribution.csv
│   ├── capping_cubes_generated.csv
│   └── summary.txt
├── corrections_YYYYMMDD_HHMMSS/      # Après ajustement cappings (Option 2)
│   ├── [mêmes fichiers que run_*]
│   └── [versions recalculées]
└── final_YYYYMMDD_HHMMSS/            # Export final (Option 3)
    ├── final_price_offers.csv
    ├── validation_report.csv
    └── export_summary.txt

Scope temporel : Les dossiers sont horodatés au moment de l'exécution. Les données extraites couvrent les 4 derniers trimestres fiscaux complets par rapport à la date d'exécution.


Fichier 1 : recommendations_detail.csv

Description

Export ligne à ligne de TOUTES les recommandations calculées. C'est le fichier le plus complet contenant la cascade complète de calcul.

Scope : ZOOM1 uniquement, offres de prix valides au moment de l'extraction.

Scope temporel : - Offres actuelles : valides au moment de l'exécution (DT_FIN > date du jour) - Historique transactionnel : 4 derniers trimestres fiscaux complets - Exemple : si exécution le 15/01/2025, historique couvre 4 quarters avant Q4 2024

Structure détaillée

Bloc 1 : Identifiants et infos condition (colonnes 1-7)

ID_CLN              : Identifiant client Sysco
LC_CLN              : Libellé client
ID_ART              : Identifiant article Sysco
LC_ART              : Libellé article
ID_CND              : Identifiant condition de prix
DT_DEB_CONDITION    : Date début validité condition
DT_FIN_CONDITION    : Date fin validité condition

Bloc 2 : Catégories produit (colonnes 8-15)

CATEGORIE_N1 à N6   : Hiérarchie article complète (du plus agrégé au plus fin)
MARQUE              : Marque produit
LC_ATTRIBUT         : Attribut produit (ex: "Basiques", "Premium")
Note : LC_ATTRIBUT = "Basiques" déclenche le capping à +50% en cascade.

Bloc 3 : Dimensions tarifaires (colonnes 16-20)

TYPE_CLIENT         : Segment client (ex: "RCI PI GI", "RSI HM")
TYPE_RESTAURANT     : Type établissement (ex: "TRADITIONNEL", "RESTAURATION_RAPIDE")
GEO                 : Zone géographique (ex: "NORD", "SUD")
UNIVERS             : ZOOM1 (exclusif dans PT2QE)
MATCH_TYPE          : Type de matching corridor
                      - "MASTER" : corridor spécifique trouvé
                      - "NATIONAL" : fallback corridor national

Bloc 4 : Métriques transactionnelles 4Q (colonnes 21-29)

Scope temporel : 4 derniers trimestres fiscaux complets

MT_CAB_4Q           : CA total sur période (hors prix promo)
QT_UF_4Q            : Volume en UF (Unité de Facturation) sur période
QT_KG_4Q            : Volume en KG sur période

MT_CAB_4Q_FERMES    : CA sur prix fermes uniquement
QT_UF_4Q_FERMES     : Volume UF sur prix fermes
QT_KG_4Q_FERMES     : Volume KG sur prix fermes

MT_CAB_4Q_INDEXES   : CA sur prix indexés uniquement
QT_UF_4Q_INDEXES    : Volume UF sur prix indexés
QT_KG_4Q_INDEXES    : Volume KG sur prix indexés

Filtres appliqués : - Hors prix promo (TRIM(LC_PRP_N1) <> 'Prix promo') - Factures ZF2 uniquement - FG_PRESTA = '0' (hors prestations) - FG_MARCHANDISE IN ('X', '1')

Bloc 5 : Prix actuels et positions (colonnes 30-33)

PRIX_TARIF_ACTUEL                               : Prix condition actuelle
PRIX_UNITAIRE_ACTUEL                            : Prix unitaire (identique à PRIX_TARIF_ACTUEL)

POSITION_TARIF_ACTUEL_DANS_ANCIENNES_BORNES    : Position dans corridor PT0CE
                                                  Valeurs: ABOVE_PRB, PL1, PL2, PL3, 
                                                          PL4, PL5, PL6, PLX, BELOW_PAS

PALIER_TARIF_ACTUEL_VS_NOUVELLES_BORNES        : Position dans corridor PT1CE
                                                  (après recalibrage PT1CE)
                                                  Valeurs: idem ci-dessus

POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES    : Position après application reco PT2QE
                                                  Valeurs: idem ci-dessus

Les 3 positions permettent de voir : 1. D'où on part (anciennes bornes) 2. Où on est après recalibrage PT1CE 3. Où on arrive après optimisation PT2QE

Bloc 6 : Cascade de calcul recommandations (colonnes 34-37)

RECO1_BASE                          : Repositionnement paliers BRUT (sans capping)
RECO1_APRES_CAPPING_SENSIBILITE    : Après étape 1 de capping (HIGH/MEDIUM/LOW)
RECO1_AVEC_CAPPING                  : Après cascade complète (sensibilité + basiques 50%)
RECO2                               : Hausse proportionnelle au PAS

Cascade visible :

RECO1_BASE
    ↓ capping sensibilité (2.5%, 5%, 7.5% selon HIGH/MEDIUM/LOW)
RECO1_APRES_CAPPING_SENSIBILITE
    ↓ capping basiques (+50% max si LC_ATTRIBUT = "Basiques")
RECO1_AVEC_CAPPING

Bloc 7 : Décision finale et traçabilité (colonnes 38-42)

DECISION_PATH       : Chemin emprunté dans l'arbre de décision
                      - "PAS_BAISSE_GEL_PRIX" : Gel total (NEW_PAS < PAS_ACTIF)
                      - "PL1_CONSERVATION_PREMIUM" : Maintien clients premium
                      - "OPTIMISATION_STANDARD" : Optimisation classique

RECO_TYPE          : Type recommandation gagnante (description courte)
                     - "GEL_PRIX"
                     - "CONSERVATION_PREMIUM"
                     - "REPOSITIONNEMENT_PALIERS"
                     - "HAUSSE_PROPORTIONNELLE_PAS"

RECO_SELECTIONNEE  : Nom explicite de la recommandation retenue
                     - "GEL_PRIX"
                     - "CONSERVATION_PREMIUM"
                     - "RECO1_REPOSITIONNEMENT_PALIERS"
                     - "RECO2_HAUSSE_PROPORTIONNELLE_PAS"

CAPPING_APPLIED    : Capping le plus contraignant appliqué (ordre priorité)
                     1. "GEL_PAS" : Gel total
                     2. "PRB_FINAL" : Plafond PRB absolu
                     3. "PLANCHER_PL2_PL3" : Plancher sécurité (CHEMIN 2)
                     4. "BASIQUES_50PCT" : Capping produits basiques
                     5. "SENSIBILITE" : Capping sensibilité prix
                     6. "NONE" : Aucun capping

Bloc 8 : Résultat final (colonnes 43-44)

PRIX_RECOMMANDE     : Prix final après arbre décision + capping PRB
PCT_HAUSSE_FINALE   : % hausse appliqué (format décimal : 0.0345 = 3.45%)

Format fichier

  • Séparateur : point-virgule (;)
  • Décimale : virgule (,)
  • Encoding : CP1252 (compatible Excel Windows)
  • Tri : PCT_HAUSSE_FINALE DESC (hausses les plus fortes en premier)

Exemple de lignes

ID_CLN;LC_CLN;ID_ART;LC_ART;TYPE_CLIENT;PRIX_TARIF_ACTUEL;RECO1_BASE;RECO1_AVEC_CAPPING;RECO2;PRIX_RECOMMANDE;PCT_HAUSSE_FINALE;DECISION_PATH;CAPPING_APPLIED
12345;RESTAURANT CHEZ PAUL;075130;FILET BOEUF 1KG;RCI PI GI;45,750;48,200;47,900;47,500;47,900;4,70;OPTIMISATION_STANDARD;SENSIBILITE
12346;BRASSERIE DU CENTRE;075131;SAUMON FUME 500G;RSI HM;28,500;28,500;28,500;29,350;28,500;0,00;PAS_BAISSE_GEL_PRIX;GEL_PAS

Comment modifier le tri

Localisation : analyze_recommendations.py ligne ~55

Modifier la clause ORDER BY :

ORDER BY PCT_HAUSSE_FINALE DESC  -- Changer selon besoin

Exemples de tris alternatifs :

ORDER BY TYPE_CLIENT, TYPE_RESTAURANT, ID_CLN, ID_ART  -- Tri logique
ORDER BY MT_CAB_4Q DESC                                 -- Plus gros CA d'abord
ORDER BY ID_CLN, ID_ART                                 -- Tri client/article

Comment ajouter une colonne

Localisation : analyze_recommendations.py méthode _export_recommendations_detail

  1. Ajouter la colonne dans le SELECT :

    SELECT
        -- Colonnes existantes
        ID_CLN,
        LC_CLN,
        -- ... autres colonnes
    
        -- Nouvelle colonne
        NEW_PAS,
        NEW_PRB,
    
    FROM {table}
    

  2. Aucune modification du code Python nécessaire (lecture automatique)


Fichier 2 : statistics_by_dimension.csv

Description

Agrégations par dimension clé (TYPE_CLIENT, TYPE_RESTAURANT, UNIVERS).

Scope : ZOOM1 uniquement

Structure

DIMENSION          : Nom de la dimension ("TYPE_CLIENT", "TYPE_RESTAURANT", "UNIVERS")
VALEUR             : Valeur spécifique de la dimension (ex: "RCI PI GI")
NB_OFFRES          : Nombre d'offres dans ce segment
NB_CLIENTS         : Clients uniques
NB_ARTICLES        : Articles uniques
PRIX_MOY_ACTUEL    : Prix moyen actuel
PRIX_MOY_RECOMMANDE: Prix moyen recommandé
PCT_HAUSSE_MOY     : Hausse moyenne en % (format décimal)
PCT_HAUSSE_MIN     : Hausse minimale
PCT_HAUSSE_MAX     : Hausse maximale
PCT_HAUSSE_STDDEV  : Écart-type des hausses

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252

Exemple

DIMENSION;VALEUR;NB_OFFRES;NB_CLIENTS;NB_ARTICLES;PRIX_MOY_ACTUEL;PRIX_MOY_RECOMMANDE;PCT_HAUSSE_MOY
TYPE_CLIENT;RCI PI GI;234567;12345;8765;34,56;35,78;3,53
TYPE_CLIENT;RSI HM;123456;6789;5432;28,90;29,75;2,94
TYPE_RESTAURANT;TRADITIONNEL;189012;8901;7654;31,23;32,18;3,04

Comment ajouter une dimension

Localisation : analyze_recommendations.py méthode _export_statistics_by_dimension

Dupliquer un des blocs de requête :

query_geo = f"""
SELECT
    'GEO' as DIMENSION,
    GEO as VALEUR,
    COUNT(*) as NB_OFFRES,
    -- ... autres métriques
FROM {table}
GROUP BY GEO
"""

Ajouter à la liste :

for query in [query_client, query_restaurant, query_univers, query_geo]:


Fichier 3 : impact_analysis.csv

Description

Analyse d'impact CA et distribution des hausses par segment TYPE_CLIENT × UNIVERS.

Scope : ZOOM1 uniquement

Structure

Métriques volumétriques

TYPE_CLIENT         : Segment client
UNIVERS             : ZOOM1
NB_OFFRES           : Nombre d'offres dans le segment

Métriques CA

CA_ACTUEL           : Somme des prix tarif actuels (€, 2 décimales)
CA_FUTUR            : Somme des prix recommandés (€, 2 décimales)
IMPACT_EUROS        : Gain CA en euros (CA_FUTUR - CA_ACTUEL)
IMPACT_PCT          : Gain CA en % ((CA_FUTUR/CA_ACTUEL - 1) × 100)
HAUSSE_MOY_PCT      : Hausse moyenne pondérée (%)

Formule IMPACT_PCT :

ROUND((CA_FUTUR - CA_ACTUEL) / CA_ACTUEL * 100, 2)

Distribution des hausses (nombres absolus)

NB_SANS_HAUSSE      : Offres avec 0% de hausse
NB_0_2PCT           : Offres ]0%, 2%]
NB_2_5PCT           : Offres ]2%, 5%]
NB_5_10PCT          : Offres ]5%, 10%]
NB_10_15PCT         : Offres ]10%, 15%]
NB_15_20PCT         : Offres ]15%, 20%]
NB_PLUS_20PCT       : Offres > 20%

Distribution des hausses (pourcentages)

PCT_SANS_HAUSSE     : % d'offres sans hausse
PCT_0_2             : % d'offres 0-2%
PCT_2_5             : % d'offres 2-5%
PCT_5_10            : % d'offres 5-10%
PCT_10_15           : % d'offres 10-15%
PCT_15_20           : % d'offres 15-20%
PCT_PLUS_20         : % d'offres > 20%

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : TYPE_CLIENT, UNIVERS

Exemple

TYPE_CLIENT;UNIVERS;NB_OFFRES;CA_ACTUEL;CA_FUTUR;IMPACT_EUROS;IMPACT_PCT;HAUSSE_MOY_PCT;NB_SANS_HAUSSE;NB_0_2PCT;PCT_SANS_HAUSSE;PCT_0_2
RCI PI GI;ZOOM1;234567;12345678,50;12789456,30;443777,80;3,59;3,78;23456;89012;10,0;37,9

Comment modifier les tranches de distribution

Localisation : analyze_recommendations.py ligne ~195

Modifier les seuils dans les CASE :

-- Exemple : ajouter une tranche 0-1%
SUM(CASE WHEN PCT_HAUSSE_FINALE > 0 AND PCT_HAUSSE_FINALE <= 0.01 THEN 1 ELSE 0 END) as NB_0_1PCT,
SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.01 AND PCT_HAUSSE_FINALE <= 0.02 THEN 1 ELSE 0 END) as NB_1_2PCT,

Ajouter aussi le calcul du pourcentage :

ROUND(NB_0_1PCT * 100.0 / NB_OFFRES, 1) as PCT_0_1,


Fichier 4 : price_increase_distribution.csv

Description

Histogramme global des hausses de prix par tranche détaillée (10 buckets).

Scope : ZOOM1, toutes offres confondues

Structure

TRANCHE_HAUSSE          : Libellé de la tranche
                          Format: "01. 0-2%", "02. 2-5%", etc.
                          Préfixe numérique pour tri correct

NB_OFFRES               : Nombre d'offres dans cette tranche
NB_CLIENTS_UNIQUES      : Clients distincts touchés
NB_ARTICLES_UNIQUES     : Articles distincts touchés

PRIX_MOY_ACTUEL         : Prix moyen actuel dans la tranche (€, 2 déc)
PRIX_MOY_RECOMMANDE     : Prix moyen recommandé dans la tranche (€, 2 déc)

HAUSSE_MIN_PCT          : Hausse minimale dans la tranche (%, 2 déc)
HAUSSE_MAX_PCT          : Hausse maximale dans la tranche (%, 2 déc)
HAUSSE_MOY_PCT          : Hausse moyenne dans la tranche (%, 2 déc)

PCT_OFFRES              : % du total des offres (1 déc)
PCT_CUMULE              : % cumulé (1 déc)

Tranches utilisées

00. Pas de hausse       : 0%
01. 0-2%                : ]0%, 2%]
02. 2-5%                : ]2%, 5%]
03. 5-7%                : ]5%, 7%]
04. 7-10%               : ]7%, 10%]
05. 10-12%              : ]10%, 12%]
06. 12-15%              : ]12%, 15%]
07. 15-17%              : ]15%, 17%]
08. 17-20%              : ]17%, 20%]
09. Plus de 20%         : > 20%

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : TRANCHE_HAUSSE (ordre numérique du préfixe)

Exemple

TRANCHE_HAUSSE;NB_OFFRES;NB_CLIENTS_UNIQUES;NB_ARTICLES_UNIQUES;PRIX_MOY_ACTUEL;PRIX_MOY_RECOMMANDE;HAUSSE_MIN_PCT;HAUSSE_MAX_PCT;HAUSSE_MOY_PCT;PCT_OFFRES;PCT_CUMULE
00. Pas de hausse;45678;3456;2345;32,45;32,45;0,00;0,00;0,00;15,2;15,2
01. 0-2%;78901;5678;4321;28,90;29,35;0,05;2,00;1,23;26,3;41,5
02. 2-5%;98765;6789;5432;31,23;32,45;2,01;5,00;3,45;32,9;74,4

Interprétation

Profil conservateur : - 80%+ des offres entre 0-10% - PCT_CUMULE atteint 90% à la tranche 7-10%

Profil agressif : - 50%+ des offres entre 10-20% - PCT_CUMULE atteint 90% à la tranche 15-17%

Profil problématique : - 20%+ des offres > 20% - Investigation nécessaire

Comment modifier les tranches

Localisation : analyze_recommendations.py ligne ~247

Modifier les CASE dans la requête :

CASE
    WHEN PCT_HAUSSE_FINALE = 0 THEN '00. Pas de hausse'
    WHEN PCT_HAUSSE_FINALE <= 0.02 THEN '01. 0-2%%'
    -- Ajouter/modifier tranches ici
    WHEN PCT_HAUSSE_FINALE <= 0.03 THEN '02. 2-3%%'  -- Nouvelle tranche
    WHEN PCT_HAUSSE_FINALE <= 0.05 THEN '03. 3-5%%'
    -- etc.
END as TRANCHE_HAUSSE

Attention : Dupliquer le CASE dans GROUP BY et ORDER BY.


Fichier 5 : decision_path_analysis.csv ⭐ NOUVEAU

Description

Statistiques par chemin de décision de l'arbre PT2QE. Permet de comprendre la répartition des offres entre les 3 chemins et l'impact de chaque type de capping.

Scope : ZOOM1 uniquement

Structure

DECISION_PATH           : Chemin emprunté (3 valeurs possibles)
                          - "PAS_BAISSE_GEL_PRIX"
                          - "PL1_CONSERVATION_PREMIUM"
                          - "OPTIMISATION_STANDARD"

RECO_SELECTIONNEE       : Recommandation retenue (nom explicite)
                          - "GEL_PRIX"
                          - "CONSERVATION_PREMIUM"
                          - "RECO1_REPOSITIONNEMENT_PALIERS"
                          - "RECO2_HAUSSE_PROPORTIONNELLE_PAS"

NB_OFFRES               : Volume d'offres par combinaison
NB_CLIENTS              : Clients distincts
NB_ARTICLES             : Articles distincts

HAUSSE_MOY_PCT          : Hausse moyenne (%, 2 déc)
HAUSSE_MEDIANE_PCT      : Hausse médiane (%, 2 déc)

-- Comptage par type de capping appliqué
NB_CAP_GEL              : Nombre avec capping GEL_PAS
NB_CAP_PRB              : Nombre avec capping PRB_FINAL
NB_CAP_PLANCHER         : Nombre avec capping PLANCHER_PL2_PL3
NB_CAP_BASIQUES         : Nombre avec capping BASIQUES_50PCT
NB_CAP_SENSIBILITE      : Nombre avec capping SENSIBILITE
NB_SANS_CAPPING         : Nombre sans capping (NONE)

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : DECISION_PATH, RECO_SELECTIONNEE

Exemple

DECISION_PATH;RECO_SELECTIONNEE;NB_OFFRES;NB_CLIENTS;NB_ARTICLES;HAUSSE_MOY_PCT;HAUSSE_MEDIANE_PCT;NB_CAP_GEL;NB_CAP_PRB;NB_CAP_PLANCHER;NB_CAP_BASIQUES;NB_CAP_SENSIBILITE;NB_SANS_CAPPING
PAS_BAISSE_GEL_PRIX;GEL_PRIX;12345;1234;987;0,00;0,00;12345;0;0;0;0;0
PL1_CONSERVATION_PREMIUM;CONSERVATION_PREMIUM;8901;890;654;1,23;0,85;0;234;4567;0;0;4100
OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;189012;12345;8765;4,56;4,23;0;5678;0;12345;98765;72224
OPTIMISATION_STANDARD;RECO2_HAUSSE_PROPORTIONNELLE_PAS;45678;4567;3456;2,89;2,67;0;1234;0;0;0;44444

Interprétation

Insight 1 - Répartition entre chemins : Si 80% des offres sont en OPTIMISATION_STANDARD, cela indique que : - Peu de baisses de PAS (CHEMIN 1) - Peu de clients premium PL1 (CHEMIN 2) - Majorité en optimisation classique (CHEMIN 3)

Insight 2 - RECO1 vs RECO2 (CHEMIN 3 uniquement) : Si RECO1 gagne dans 90% des cas du CHEMIN 3 : - Les paliers sont bien calibrés - Le repositionnement est plus agressif que la hausse proportionnelle - Les cappings ne sont pas trop contraignants

Insight 3 - Impact des cappings : - NB_CAP_SENSIBILITE élevé → Cappings sensibilité actifs - NB_CAP_BASIQUES élevé → Beaucoup de produits basiques dépassent +50% - NB_CAP_PRB élevé → Compression du corridor (écart PAS-PRB réduit) - NB_SANS_CAPPING élevé → Cappings peu contraignants OU prix déjà bas

Comment utiliser ce fichier

Cas 1 : Ajuster l'agressivité globale - Si trop de RECO2 gagne → Hausser les paliers dans PT1CE - Si trop de RECO1 gagne → Baisser les paliers OU augmenter les cappings

Cas 2 : Calibrer les cappings - Si NB_CAP_SENSIBILITE > 50% des offres → Cappings trop restrictifs - Modifier inputs/capping_type_client.csv

Cas 3 : Analyser les gels - Si NB_CAP_GEL élevé → Beaucoup de baisses de PAS - Vérifier PT1CE : les nouveaux PAS sont-ils cohérents ?


Fichier 6 : capping_distribution.csv ⭐ NOUVEAU

Description

Distribution détaillée des cappings appliqués, croisée avec chemins de décision et recommandations. Vision granulaire de l'impact de chaque type de capping.

Scope : ZOOM1 uniquement

Structure

CAPPING_APPLIED         : Type de capping le plus contraignant
                          Ordre priorité (du plus au moins prioritaire):
                          1. "GEL_PAS"
                          2. "PRB_FINAL"
                          3. "PLANCHER_PL2_PL3"
                          4. "BASIQUES_50PCT"
                          5. "SENSIBILITE"
                          6. "NONE"

DECISION_PATH           : Chemin de décision
RECO_SELECTIONNEE       : Recommandation retenue

NB_OFFRES               : Volume d'offres
HAUSSE_MOY_PCT          : Hausse moyenne (%, 2 déc)

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : CAPPING_APPLIED, DECISION_PATH, RECO_SELECTIONNEE

Exemple

CAPPING_APPLIED;DECISION_PATH;RECO_SELECTIONNEE;NB_OFFRES;HAUSSE_MOY_PCT
GEL_PAS;PAS_BAISSE_GEL_PRIX;GEL_PRIX;12345;0,00
PRB_FINAL;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;5678;7,89
PLANCHER_PL2_PL3;PL1_CONSERVATION_PREMIUM;CONSERVATION_PREMIUM;4567;1,23
BASIQUES_50PCT;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;12345;35,67
SENSIBILITE;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;98765;4,56
NONE;OPTIMISATION_STANDARD;RECO2_HAUSSE_PROPORTIONNELLE_PAS;44444;2,89

Interprétation

Analyse capping BASIQUES_50PCT :

BASIQUES_50PCT;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;12345;35,67
- 12345 offres de produits basiques - HAUSSE_MOY = 35,67% → Sans capping, hausse aurait été > 50% - Preuve que le capping basiques est actif et utile - Si HAUSSE_MOY proche de 50% → Beaucoup d'offres plafonnées

Analyse capping SENSIBILITE :

SENSIBILITE;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;98765;4,56
- 98765 offres plafonnées par capping sensibilité - HAUSSE_MOY = 4,56% → Probablement LOW sensitivity (7,5%) - Si volume très élevé → Cappings peut-être trop restrictifs

Analyse NONE :

NONE;OPTIMISATION_STANDARD;RECO2_HAUSSE_PROPORTIONNELLE_PAS;44444;2,89
- 44444 offres sans capping appliqué - RECO2 gagne souvent dans ce cas - HAUSSE_MOY faible (2,89%) → Prix déjà bien positionnés

Comment utiliser ce fichier

Cas 1 : Évaluer l'efficacité des cappings basiques - Filtrer CAPPING_APPLIED = 'BASIQUES_50PCT' - Si HAUSSE_MOY proche de 50% → Capping très actif - Si HAUSSE_MOY << 50% → Capping peu utile (considérer suppression)

Cas 2 : Mesurer l'impact du capping PRB - Filtrer CAPPING_APPLIED = 'PRB_FINAL' - Volume élevé → Compression du corridor (écart PAS-PRB réduit) - Solution : Réajuster PRB dans PT1CE

Cas 3 : Calibrer les cappings sensibilité - Comparer NB_OFFRES entre SENSIBILITE et NONE - Si SENSIBILITE >> NONE → Cappings trop contraignants - Augmenter les valeurs dans inputs/capping_type_client.csv

Comment modifier l'ordre de priorité des cappings

Localisation : calculate_recommandations.py ligne ~550

L'ordre de priorité est défini dans le CASE de la requête SQL :

CASE
    -- Priorité 1 : Gel total
    WHEN fp.DECISION_PATH = 'PAS_BAISSE_GEL_PRIX' 
    THEN 'GEL_PAS'

    -- Priorité 2 : Capping PRB final
    WHEN fp.CAPPING_PRB_APPLIED = 1 
    THEN 'PRB_FINAL'

    -- Priorité 3 : Plancher PL2_PL3
    WHEN fp.PLANCHER_PL2_APPLIED = 1 
    THEN 'PLANCHER_PL2_PL3'

    -- Priorité 4 : Capping basiques (NOUVEAU)
    WHEN fp.CAPPING_BASIQUES_APPLIED = 1
    THEN 'BASIQUES_50PCT'

    -- Priorité 5 : Capping sensibilité
    WHEN fp.CAPPING_SENSIBILITE_APPLIED = 1 
    THEN 'SENSIBILITE'

    -- Aucun capping
    ELSE 'NONE'
END as CAPPING_APPLIED

Pour modifier l'ordre : Réorganiser les WHEN par priorité descendante.


Fichier 7 : capping_cubes_generated.csv

Description

Cappings générés pour chaque cube (UNIVERS × TYPE_CLIENT × TYPE_RESTAURANT × GEO). Ce fichier sert de base pour les ajustements manuels.

Scope : ZOOM1 uniquement, cubes MASTER + NATIONAL

Structure

UNIVERS             : ZOOM1
TYPE_CLIENT         : Segment client ou "NATIONAL"
TYPE_RESTAURANT     : Type restaurant ou "NATIONAL"
GEO                 : Zone géographique ou "NATIONAL"
CUBE_TYPE           : "MASTER" (cube spécifique) ou "NATIONAL" (fallback)

CAPPING_HIGH        : Capping pour produits HIGH sensitivity (format décimal)
CAPPING_MEDIUM      : Capping pour produits MEDIUM sensitivity
CAPPING_LOW         : Capping pour produits LOW sensitivity

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : UNIVERS, TYPE_CLIENT, TYPE_RESTAURANT, GEO

Exemple

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;TRADITIONNEL;NORD;MASTER;0,025;0,05;0,075
ZOOM1;RCI PI GI;TRADITIONNEL;SUD;MASTER;0,025;0,05;0,075
ZOOM1;RSI HM;RESTAURATION_RAPIDE;EST;MASTER;0,025;0,05;0,075
ZOOM1;NATIONAL;NATIONAL;NATIONAL;NATIONAL;0,03;0,10;0,15

Cubes NATIONAL

Les cubes NATIONAL servent de fallback pour les offres qui n'ont pas de corridor MASTER.

Cappings par défaut : - CAPPING_HIGH : 0,03 (3% - plus restrictif) - CAPPING_MEDIUM : 0,10 (10%) - CAPPING_LOW : 0,15 (15%)

Rationale : Les corridors nationaux sont moins précis, donc cappings plus conservateurs.

Comment utiliser ce fichier pour ajuster les cappings

Procédure complète :

  1. Analyser les résultats initiaux (après Option 1)
  2. Ouvrir recommendations_detail.csv
  3. Filtrer sur TYPE_CLIENT / TYPE_RESTAURANT / GEO spécifique
  4. Examiner PCT_HAUSSE_FINALE et CAPPING_APPLIED

  5. Identifier les cubes à ajuster

  6. Hausses trop fortes → Baisser les cappings
  7. Hausses trop faibles → Augmenter les cappings
  8. Beaucoup de CAPPING_APPLIED = 'SENSIBILITE' → Cappings trop restrictifs

  9. Copier le fichier vers corrections/

    Copier : outputs/run_YYYYMMDD_HHMMSS/capping_cubes_generated.csv
    Vers   : corrections/capping_cubes_corrections.csv
    

  10. Modifier les valeurs dans Excel

  11. Ouvrir corrections/capping_cubes_corrections.csv
  12. Modifier CAPPING_HIGH / MEDIUM / LOW pour les cubes souhaités
  13. Ne pas modifier : UNIVERS, TYPE_CLIENT, TYPE_RESTAURANT, GEO, CUBE_TYPE
  14. Sauvegarder avec séparateur ; et décimale ,

  15. Relancer avec Option 2 (Ajuster cappings)

  16. Exécuter 2_ajuster_cappings.bat OU Menu Option 2
  17. Les nouveaux cappings seront appliqués
  18. Nouveau dossier corrections_YYYYMMDD_HHMMSS/ généré

  19. Comparer les résultats

  20. Comparer run_*/recommendations_detail.csv vs corrections_*/recommendations_detail.csv
  21. Vérifier l'évolution de PCT_HAUSSE_FINALE
  22. Itérer si nécessaire

Exemple de modification

Avant (capping_cubes_generated.csv) :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;TRADITIONNEL;NORD;MASTER;0,025;0,05;0,075

Après correction (capping_cubes_corrections.csv) :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;TRADITIONNEL;NORD;MASTER;0,03;0,06;0,09

Impact : Produits HIGH sensitivity passent de +2,5% max à +3% max pour ce cube.


Fichier 8 : summary.txt

Description

Fichier texte récapitulatif de l'exécution. Généré à chaque run.

Scope : ZOOM1 uniquement

Contenu

PT2QE - RÉSUMÉ D'EXÉCUTION
======================================================================

Date : 15/01/2025 14:32:45
Période analysée : 2024-01-01 -> 2024-12-31
Trimestres fiscaux : 2024_Q01, 2024_Q02, 2024_Q03, 2024_Q04
Table recommandations : PT2QE_RECOMMENDATIONS
Dossier résultats : outputs/run_20250115_143245

Champs : - Date : Horodatage de l'exécution - Période analysée : Dates de début et fin de l'extraction historique (4Q) - Trimestres fiscaux : Liste des quarters inclus dans l'historique - Table recommandations : Nom de la table Oracle créée - Dossier résultats : Chemin du dossier de sortie

Comment modifier le contenu

Localisation : pt2qe_main.py fonction create_summary_file

Ajouter des lignes au fichier :

f.write(f"Date : {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}\n")
f.write(f"Période analysée : {app.start_date} -> {app.end_date}\n")
f.write(f"Trimestres fiscaux : {', '.join(app.fiscal_quarters)}\n")
f.write(f"Table recommandations : {table}\n")
f.write(f"Dossier résultats : {app.output_folder}\n")

# Ajouter nouvelles infos
f.write(f"Base de données : {app.args.database}\n")
f.write(f"Fichier capping : {app.args.capping_file}\n")


Exports finaux (Option 3)

Fichier 9 : final_price_offers.csv

Description

Export final simplifié au format client × article, prêt pour intégration. Contient uniquement les champs nécessaires pour l'utilisation opérationnelle.

Scope : ZOOM1 uniquement, offres avec recommandations calculées

Structure

Colonnes principales (format export)

ID_CLN                  : Identifiant client
LC_CLN                  : Libellé client
ID_ART                  : Identifiant article
LC_ART                  : Libellé article

TYPE_CLIENT             : Segment client
TYPE_RESTAURANT         : Type établissement
GEO                     : Zone géographique
UNIVERS                 : ZOOM1

ID_CND                  : Identifiant condition
DT_DEB_CONDITION        : Date début validité
DT_FIN_CONDITION        : Date fin validité

PRIX_TARIF_ACTUEL       : Prix actuel (€, 3 décimales)
NOUVEAU_PRIX            : Prix recommandé (€, 3 décimales)

PCT_HAUSSE              : % hausse (format 12,34 = 12,34%)
HAUSSE_EUROS            : Hausse en € (3 décimales)

Attention : PCT_HAUSSE est en format pourcentage (12,34 = 12,34%), contrairement aux autres exports où c'est en format décimal (0,1234).

Colonnes traçabilité

POSITION_TARIF_ACTUEL_DANS_ANCIENNES_BORNES    : Position départ
PALIER_TARIF_ACTUEL_VS_NOUVELLES_BORNES        : Position après PT1CE
POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES    : Position après PT2QE

PRICE_SENSITIVITY       : HIGH / MEDIUM / LOW

TYPE_HAUSSE             : Type recommandation retenue
                          - "REPOSITIONNEMENT" (RECO1)
                          - "HAUSSE_PROPORTIONNELLE" (RECO2)

VALIDATION_STATUS       : Statut validation automatique
                          - "VALIDE" : OK
                          - "A_VERIFIER" : Hausse > 20%
                          - "ANOMALIE" : Baisse détectée

DATE_CALCUL             : Horodatage calcul (format DD/MM/YYYY HH24:MI:SS)

Règles de validation automatique

VALIDE (par défaut) : - PCT_HAUSSE entre 0% et 20% - Aucune anomalie détectée

A_VERIFIER : - PCT_HAUSSE > 20% - Ou (PRICE_SENSITIVITY = 'HIGH' ET PCT_HAUSSE > 10%)

ANOMALIE : - PCT_HAUSSE < 0 (baisse de prix) - Ne devrait jamais arriver avec PT2QE

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : ID_CLN, ID_ART

Exemple

ID_CLN;LC_CLN;ID_ART;LC_ART;TYPE_CLIENT;PRIX_TARIF_ACTUEL;NOUVEAU_PRIX;PCT_HAUSSE;VALIDATION_STATUS;TYPE_HAUSSE
12345;RESTAURANT CHEZ PAUL;075130;FILET BOEUF 1KG;RCI PI GI;45,750;47,900;4,70;VALIDE;REPOSITIONNEMENT
12346;BRASSERIE DU CENTRE;075131;SAUMON FUME 500G;RSI HM;28,500;29,350;2,98;VALIDE;HAUSSE_PROPORTIONNELLE
12347;HOTEL RESTAURANT;075132;CHAMPIGNONS 1KG;RCI PI GI;12,450;15,950;28,11;A_VERIFIER;REPOSITIONNEMENT

Comment modifier les seuils de validation

Localisation : generate_final_quotes.py méthode _format_final_data

def _format_final_data(self, df: pd.DataFrame):
    # Statut par défaut
    df['VALIDATION_STATUS'] = 'VALIDE'

    # Modifier seuils ici
    df.loc[df['PCT_HAUSSE'] > 20, 'VALIDATION_STATUS'] = 'A_VERIFIER'  # Changer 20

    # Anomalies
    df.loc[df['PCT_HAUSSE'] < 0, 'VALIDATION_STATUS'] = 'ANOMALIE'

    # Cas spéciaux - modifier conditions
    df.loc[
        (df['PRICE_SENSITIVITY'] == 'HIGH') & 
        (df['PCT_HAUSSE'] > 10),  # Changer 10
        'VALIDATION_STATUS'
    ] = 'A_VERIFIER'

Comment ajouter des colonnes

Localisation : generate_final_quotes.py ligne ~30

Ajouter les colonnes dans le SELECT :

SELECT
    -- Colonnes existantes
    ID_CLN,
    LC_CLN,
    -- ...

    -- Nouvelles colonnes
    RECO1_BASE,
    RECO2,
    DECISION_PATH,
    CAPPING_APPLIED,

FROM {recommendations_table}

Aucune modification Python nécessaire (lecture auto).


Fichier 10 : validation_report.csv

Description

Rapport de validation structuré avec métriques clés.

Scope : ZOOM1 uniquement

Structure

CATEGORIE       : Type de métrique
                  - "GLOBAL" : Métriques volumétriques globales
                  - "HAUSSES" : Statistiques de hausses
                  - "TYPE_HAUSSE" : Répartition RECO1/RECO2
                  - "VALIDATION" : Distribution statuts validation

METRIQUE        : Nom de la métrique

VALEUR          : Valeur (nombre ou pourcentage)

Format

  • Séparateur : ;
  • Décimale : ,
  • Encoding : CP1252
  • Tri : CATEGORIE, METRIQUE

Exemple

CATEGORIE;METRIQUE;VALEUR
GLOBAL;Nombre total d'offres;234567
GLOBAL;Nombre de clients;12345
GLOBAL;Nombre d'articles;8765
HAUSSES;Hausse moyenne (%);3,78
HAUSSES;Hausse médiane (%);2,89
HAUSSES;Hausse max (%);28,45
TYPE_HAUSSE;REPOSITIONNEMENT;145678
TYPE_HAUSSE;HAUSSE_PROPORTIONNELLE;88889
VALIDATION;VALIDE;220123
VALIDATION;A_VERIFIER;14234
VALIDATION;ANOMALIE;210

Métriques disponibles

GLOBAL : - Nombre total d'offres - Nombre de clients - Nombre d'articles

HAUSSES : - Hausse moyenne (%) - Hausse médiane (%) - Hausse min (%) - Hausse max (%)

TYPE_HAUSSE : - REPOSITIONNEMENT (RECO1 gagne) - HAUSSE_PROPORTIONNELLE (RECO2 gagne)

VALIDATION : - VALIDE - A_VERIFIER - ANOMALIE

Comment ajouter des métriques

Localisation : generate_final_quotes.py méthode _generate_validation_report

Ajouter au tableau validation_stats :

# Nouvelle métrique
validation_stats.append({
    'CATEGORIE': 'PERFORMANCE',
    'METRIQUE': 'CA total impacté (€)',
    'VALEUR': (df['NOUVEAU_PRIX'] * df['QT_UF_4Q']).sum()
})


Fichier 11 : export_summary.txt

Description

Résumé textuel lisible de l'export final.

Scope : ZOOM1 uniquement

Contenu type

RÉSUMÉ EXPORT FINAL PT2QE
==================================================

Date : 15/01/2025 14:32:45

VOLUMÉTRIE
--------------------
Offres exportées : 234,567
Clients uniques : 12,345
Articles uniques : 8,765

HAUSSES DE PRIX
--------------------
Hausse moyenne : 3.7%
Hausse médiane : 2.9%
Hausse min : 0.0%
Hausse max : 28.5%

VALIDATION
--------------------
VALIDE : 220,123 (93.8%)
A_VERIFIER : 14,234 (6.1%)
ANOMALIE : 210 (0.1%)

RÉPARTITION TYPE RECOMMANDATION
--------------------
REPOSITIONNEMENT : 145,678 (62.1%)
HAUSSE_PROPORTIONNELLE : 88,889 (37.9%)

MATCHING CORRIDORS
--------------------
MASTER : 210,345 (89.7%)
NATIONAL : 24,222 (10.3%)

Sections

  1. Date : Horodatage génération
  2. Volumétrie : Offres, clients, articles
  3. Hausses de prix : Statistiques descriptives
  4. Validation : Distribution statuts
  5. Répartition type recommandation : RECO1 vs RECO2
  6. Matching corridors : MASTER vs NATIONAL

Comment modifier le contenu

Localisation : generate_final_quotes.py méthode _generate_validation_report

Ajouter des sections au fichier :

with open(summary_file, 'w', encoding='cp1252') as f:
    f.write("RÉSUMÉ EXPORT FINAL PT2QE\n")
    f.write("=" * 50 + "\n\n")

    # ... sections existantes ...

    # Nouvelle section
    f.write("DÉTAIL PAR TYPE CLIENT\n")
    f.write("-" * 20 + "\n")
    type_client_stats = df.groupby('TYPE_CLIENT').agg({
        'ID_CLN': 'count',
        'PCT_HAUSSE': 'mean'
    })
    for tc, stats in type_client_stats.iterrows():
        f.write(f"{tc} : {stats['ID_CLN']:,} offres, {stats['PCT_HAUSSE']:.1f}% hausse moy\n")


Paramètres d'export globaux

Configuration dans pt2qe_config.json

Localisation : config/pt2qe_config.json

{
    "output": {
        "csv_separator": ";",
        "csv_encoding": "cp1252",
        "decimal_places": 3,
        "percentage_format": 2
    }
}

Paramètres disponibles

csv_separator       : Séparateur CSV (défaut: ;)
csv_encoding        : Encodage (défaut: cp1252 pour Excel Windows)
decimal_places      : Décimales pour les montants (défaut: 3)
percentage_format   : Décimales pour les pourcentages (défaut: 2)

Comment modifier l'encodage pour Linux/Mac

Modifier dans pt2qe_config.json :

{
    "output": {
        "csv_separator": ",",
        "csv_encoding": "utf-8",
        "decimal_places": 3,
        "percentage_format": 2
    }
}

Attention : Changer aussi le séparateur décimal dans le code si nécessaire.

Comment modifier le séparateur décimal

Localisation : Chaque méthode d'export dans analyze_recommendations.py et generate_final_quotes.py

Remplacer decimal=',' par decimal='.' :

df.to_csv(output_file, index=False, sep=';', decimal='.', encoding='utf-8')


Volumétrie et performance

Compression automatique

Les exports ne sont pas compressés automatiquement par défaut.

Compression manuelle :

Sous Windows :

cd outputs\run_YYYYMMDD_HHMMSS
7z a exports.zip *.csv *.txt

Sous Linux :

cd outputs/run_YYYYMMDD_HHMMSS
zip exports.zip *.csv *.txt

Comment activer la compression automatique

Créer un fichier compress_exports.py dans utils/ :

import zipfile
from pathlib import Path

def compress_exports(output_folder: Path):
    csv_files = list(output_folder.glob('*.csv'))
    txt_files = list(output_folder.glob('*.txt'))

    if csv_files or txt_files:
        zip_path = output_folder / 'exports.zip'
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:
            for f in csv_files + txt_files:
                zf.write(f, f.name)
                f.unlink()  # Supprimer après compression

Appeler dans pt2qe_main.py après génération :

from utils.compress_exports import compress_exports

# Après génération des exports
compress_exports(app.output_folder)


Découpage des exports volumineux

Exports sans découpage

Par défaut, aucun découpage n'est appliqué. Tous les exports sont en un seul fichier.

Comment activer le découpage

Localisation : analyze_recommendations.py méthode _export_recommendations_detail

Ajouter avant df.to_csv() :

def split_dataframe(df, chunk_size=500000):
    """Découpe un DataFrame en chunks."""
    for i in range(0, len(df), chunk_size):
        yield df.iloc[i:i+chunk_size]

# Dans _export_recommendations_detail
if len(df) > 500000:
    # Découpage nécessaire
    for i, chunk in enumerate(split_dataframe(df, chunk_size=500000)):
        chunk_file = output_folder / f'recommendations_detail_part{i+1:02d}.csv'
        chunk.to_csv(chunk_file, index=False, sep=';', decimal=',', encoding='cp1252')
        self.app.log.info(f"    → Part {i+1} : {len(chunk):,} lignes")
else:
    # Export normal
    df.to_csv(output_file, index=False, sep=';', decimal=',', encoding='cp1252')


Utilisation des exports

Workflow standard

1. Exécuter Option 1 (Calcul recommandations)
   └─> Analyser : recommendations_detail.csv
       decision_path_analysis.csv
       capping_distribution.csv

2. Si ajustements nécessaires
   └─> Modifier : corrections/capping_cubes_corrections.csv
   └─> Exécuter Option 2 (Ajuster cappings)
   └─> Comparer : run_*/recommendations_detail.csv
                  vs corrections_*/recommendations_detail.csv

3. Si résultats validés
   └─> Exécuter Option 3 (Générer offres finales)
   └─> Utiliser : final_price_offers.csv

Analyses Excel recommandées

Sur recommendations_detail.csv : 1. Tableau croisé dynamique : TYPE_CLIENT × UNIVERS - Valeurs : Moyenne PCT_HAUSSE_FINALE - Filtres : DECISION_PATH, CAPPING_APPLIED

  1. Graphique distribution PCT_HAUSSE_FINALE
  2. Histogramme par tranches
  3. Courbe cumulée

Sur decision_path_analysis.csv : 1. Graphique empilé : Volume par DECISION_PATH - Couleurs par RECO_SELECTIONNEE

  1. Tableau : Impact des cappings par chemin
  2. Lignes : DECISION_PATH
  3. Colonnes : NB_CAP_* (comptages)

Sur impact_analysis.csv : 1. Tableau : TYPE_CLIENT × IMPACT_PCT - Mise en forme conditionnelle selon impact

  1. Graphique : Distribution des hausses
  2. Barres : NB_0_2PCT, NB_2_5PCT, etc.
  3. Courbe : PCT cumulés

Troubleshooting

Problème : Fichiers CSV illisibles dans Excel

Cause : Encodage CP1252 corrompu ou séparateurs mal détectés

Solution 1 : Réimporter dans Excel - Données → Obtenir des données → À partir d'un fichier texte - Choisir "Délimité" → Séparateur ";" → Décimale "," - Encodage : Windows-1252

Solution 2 : Modifier l'encodage

# Dans pt2qe_config.json
"csv_encoding": "utf-8-sig"  # UTF-8 avec BOM pour Excel

Problème : Colonnes manquantes dans l'export

Cause : Colonne ajoutée dans la requête SQL mais pas dans le DataFrame

Solution : Vérifier que le SELECT inclut toutes les colonnes

Dans analyze_recommendations.py :

# Vérifier la requête
query = f"""
SELECT
    ID_CLN,
    LC_CLN,
    ID_ART,
    -- ... TOUTES les colonnes nécessaires
FROM {table}
"""

Problème : Pourcentages mal formatés

Cause : Format décimal au lieu de format pourcentage

Solution : Convertir dans le code

Pour les exports détaillés (format décimal 0.0345) :

# Aucune conversion nécessaire
df['PCT_HAUSSE_FINALE'] = df['PCT_HAUSSE_FINALE']  # Reste en décimal

Pour l'export final (format pourcentage 3.45) :

# Conversion nécessaire
df['PCT_HAUSSE'] = (df['PCT_HAUSSE_FINALE'] * 100).round(2)

Problème : Exports très volumineux

Cause : Volume ZOOM1 important

Solution 1 : Filtrer dans la requête SQL

-- Ajouter des WHERE dans la requête d'export
WHERE TYPE_CLIENT = 'RCI PI GI'  -- Filtrer sur un segment

Solution 2 : Activer le découpage (voir section précédente)

Solution 3 : Exporter par batch

# Dans _export_recommendations_detail
for type_client in ['RCI PI GI', 'RSI HM', 'RSC HM']:
    query_filtered = f"{query} WHERE TYPE_CLIENT = '{type_client}'"
    # ... export

Problème : Dossiers outputs/ non créés

Cause : Permissions ou erreur création dossier

Solution : Vérifier les permissions

# Dans pt2qe_main.py
app.output_folder.mkdir(parents=True, exist_ok=True)

Si erreur persiste, créer manuellement :

mkdir outputs

Problème : Fichiers exports vides

Cause : Aucune donnée dans la table source

Solution : Vérifier le contenu de la table

SELECT COUNT(*) FROM PT2QE_RECOMMENDATIONS;

Si 0 ligne → Problème lors du calcul des recommandations.


Personnalisation avancée

Ajouter un export custom

Localisation : analyze_recommendations.py

Créer une nouvelle méthode :

def _export_custom_analysis(self, table: str, output_folder: Path):
    """Mon export personnalisé."""
    output_file = output_folder / 'custom_export.csv'

    query = f"""
    SELECT
        TYPE_CLIENT,
        COUNT(*) as NB_OFFRES,
        AVG(PCT_HAUSSE_FINALE) as HAUSSE_MOY
        -- Ajouter colonnes souhaitées
    FROM {table}
    GROUP BY TYPE_CLIENT
    ORDER BY TYPE_CLIENT
    """

    q = self.db.create_query(query)
    df = q.read()
    q.close()

    if not df.empty:
        df.to_csv(output_file, index=False, sep=';', decimal=',', encoding='cp1252')
        self.app.log.info(f"    → Export custom généré")

Appeler dans analyze_and_export :

def analyze_and_export(self, recommendations_table: str, output_folder: Path):
    # ... exports existants ...

    # Nouvel export
    self._export_custom_analysis(recommendations_table, output_folder)

Modifier le format de date

Localisation : generate_final_quotes.py ligne ~30

Dans la requête SQL :

-- Changer format date
TO_CHAR(CALCULATION_DATE, 'DD/MM/YYYY HH24:MI:SS') as DATE_CALCUL  -- Actuel
TO_CHAR(CALCULATION_DATE, 'YYYY-MM-DD') as DATE_CALCUL             -- ISO 8601
TO_CHAR(CALCULATION_DATE, 'MM/DD/YYYY') as DATE_CALCUL             -- US

Ajouter un export JSON

Localisation : generate_final_quotes.py

Après l'export CSV :

import json

# Export JSON en plus du CSV
json_file = output_file.parent / 'final_price_offers.json'

# Convertir DataFrame en JSON
df_json = df.to_dict(orient='records')

with open(json_file, 'w', encoding='utf-8') as f:
    json.dump(df_json, f, indent=2, ensure_ascii=False)

self.app.log.info(f"    → Export JSON généré")


Résumé des fichiers générés

Par étape d'exécution

Option 1 - Calcul initial (run_YYYYMMDD_HHMMSS/) : - ✅ recommendations_detail.csv - ✅ statistics_by_dimension.csv - ✅ impact_analysis.csv - ✅ price_increase_distribution.csv - ✅ decision_path_analysis.csv ⭐ NOUVEAU - ✅ capping_distribution.csv ⭐ NOUVEAU - ✅ capping_cubes_generated.csv - ✅ summary.txt

Option 2 - Après corrections (corrections_YYYYMMDD_HHMMSS/) : - Même liste que Option 1 (versions recalculées)

Option 3 - Export final (final_YYYYMMDD_HHMMSS/) : - ✅ final_price_offers.csv - ✅ validation_report.csv - ✅ export_summary.txt

Taille typique des fichiers

Impossible à estimer : Dépend du volume ZOOM1 et de la volumétrie client × article.

Fichiers obligatoires vs optionnels

Obligatoires (toujours générés) : - recommendations_detail.csv - capping_cubes_generated.csv - summary.txt - final_price_offers.csv (Option 3)

Optionnels (peuvent être désactivés) : - statistics_by_dimension.csv - impact_analysis.csv - price_increase_distribution.csv - decision_path_analysis.csv - capping_distribution.csv - validation_report.csv

Pour désactiver un export optionnel, commenter l'appel dans analyze_and_export :

# self._export_statistics_by_dimension(recommendations_table, output_folder)


Points d'attention

Scopes temporels à retenir

  1. Offres extraites : Valides au moment de l'exécution (DT_FIN > date du jour)
  2. Historique 4Q : 4 derniers trimestres fiscaux complets avant la date d'exécution
  3. Corridors PT1CE : Utilisés tels que présents dans PT1CE_OPTIMAL_* au moment de l'exécution
  4. Cappings : Fichier inputs/capping_type_client.csv utilisé lors du calcul

Cohérence entre exports

Tous les exports d'un même run (même dossier) sont cohérents : - Même extraction source - Même période 4Q - Mêmes cappings appliqués - Même horodatage

Conservation des runs

Les dossiers de run ne sont jamais écrasés. Chaque exécution crée un nouveau dossier horodaté.

Recommandation : Archiver les anciens runs après validation pour libérer de l'espace.

Encodage et compatibilité

CP1252 (défaut) : - ✅ Compatible Excel Windows (France) - ✅ Caractères accentués français - ❌ Peut poser problème sur Linux/Mac

UTF-8 (alternatif) : - ✅ Compatible tous systèmes - ✅ Standard moderne - ⚠️ Nécessite import manuel dans Excel Windows

Arrondis et précision

Montants : 3 décimales (45,750) Pourcentages : 2 décimales (3,45%) Écarts : Possible sur les agrégations (somme des arrondis ≠ arrondi de la somme)