Aller au contenu

Concepts métier - PT2QE

Vue d'ensemble du système

PT2QE (Pricing Tier 2 Quote Engine) génère des recommandations de prix personnalisées à la maille client × article. Contrairement à PT1CE qui optimise des corridors de prix génériques, PT2QE produit des offres de prix spécifiques pour chaque couple client-article.

Périmètre traité : - Univers : ZOOM1 EXCLUSIF (filtre appliqué à l'extraction et tout au long du processus) - Période d'analyse : 4 derniers trimestres fiscaux COMPLETS selon SYS_MD_CALENDRIER_SYSCO - Conditions : Types ZFAP, ZFSP, ZIAP, ZISP sur séquences A305 et A565 - État : Offres valides (DT_FIN > SYSDATE) et conditions actives (FG_CND_VLD = 'X')

Prérequis obligatoires : - Tables PT1CE_OPTIMAL_ZOOM1/ZOOM2/ZOOM3 existantes (générées par PT1CE) - Tables de mapping PT0CE_TYPE_CLIENT_MAPPING et PT0CE_TYPE_RESTAURANT_MAPPING - Table SYS_MD_CALENDRIER_SYSCO avec données fiscales à jour


Période d'analyse et historique transactionnel

Détermination automatique de la période

PT2QE utilise le calendrier fiscal Sysco (format 4-4-5) pour déterminer automatiquement la période d'analyse. Le module PeriodManager interroge SYS_MD_CALENDRIER_SYSCO pour :

  1. Identifier la date de référence : Date d'exécution du traitement
  2. Trouver les 4 derniers trimestres complets :
  3. Un trimestre est considéré "complet" si sa dernière semaine (MAX(ID_SEM)) est passée
  4. Remonte dans l'historique pour obtenir exactement 4 trimestres
  5. Retourne les dates de début et fin au format DATE Oracle

Exemple :

Date d'exécution : 2025-11-03
Trimestres identifiés : 2024_Q04, 2025_Q01, 2025_Q02, 2025_Q03
Période d'extraction : 2024-10-28 → 2025-10-26

Scope temporel de l'historique

Toutes les métriques transactionnelles sont calculées sur cette période de 4 trimestres : - MT_CAB_4Q : CA total (hors promos) - QT_UF_4Q : Volume en unités de facturation - QT_KG_4Q : Volume en kilogrammes - MT_CAB_4Q_FERMES : CA sur prix fermes uniquement - MT_CAB_4Q_INDEXES : CA sur prix indexés uniquement

Filtres transactionnels appliqués : - ID_TYP_FAC = 'ZF2' (factures de type ZF2) - LC_TC_INTRA IN ('Brake', 'D2 hors Brake') - Prix promo exclus (via jointure PRP_LABELS) - FG_PRESTA = '0' (pas de prestation) - FG_MARCHANDISE IN ('X', '1') (marchandise uniquement) - MT_CAB > 0, QT_UF > 0, MT_GM4 IS NOT NULL

Récupération du statut mercuriale (FG_HM)

Le flag FG_HM est déterminé dynamiquement depuis l'historique transactionnel : - Source : Table SYS_FACTURE_LIGNE sur la période 4Q - Logique : Dernière ligne de facture connue pour le couple client-article - Valeurs : - '1' : Hors mercuriale (prix personnalisé) - '0' : En mercuriale (prix standard) - Utilisation : Ce flag est ensuite utilisé pour déterminer l'UNIVERS et faire le matching avec les mappings TYPE_CLIENT


Extraction et enrichissement des offres

Phase 1 : Extraction des offres actuelles

Table source : SYS_TARIF_SIMULATION
Table de sortie : PT2QE_PRICE_OFFERS

Critères de sélection des offres :

-- Conditions valides et actives
cnd.FG_CND_VLD = 'X'
cnd.ID_ACC IS NULL
cnd.DT_FIN > SYSDATE

-- Types de conditions
cnd.ID_TYP_CND IN ('ZFAP', 'ZFSP', 'ZIAP', 'ZISP')

-- Séquences A305 ou A565
cnd.ID_SEQ IN ('A305', 'A565')

-- Séquence client ou hiérarchie
(
  (c.ID_STA_CLN IN ('10', '20', '30', '50') AND cnd.LC_SEQ_CLN = 'CLIENT')
  OR
  (c.ID_AGC <> 'A000' AND cnd.LC_SEQ_CLN IN ('HIERARCHIE CLIENT N4', 'N5', 'N6'))
)

-- Exclusions produits
a.ID_GMM <> 'PSN'
a.LC_HI1 <> 'Qualificatif article inconnu'
a.LC_HIC_SYSCO_N2 NOT IN ('Divers', 'Freezer')

-- Exclusions clients
c.ID_TC_CG <> 'AUTRES'

Phase 2 : Enrichissement avec FG_HM

Sous-requête : LAST_FG_HM
Principe : Récupérer le dernier flag mercuriale connu pour chaque couple client-article

-- Classement par date de commande décroissante
ROW_NUMBER() OVER (
  PARTITION BY c.ID_CLN, f.ID_ART 
  ORDER BY f.DT_CDE DESC, f.ID_FAC DESC
) as RN

-- Conservation du rang 1 uniquement
WHERE RN = 1

Transformation du flag : - Si TRIM(f.FG_HM) = 'X''1' - Sinon → '0'

Phase 3 : Calcul de l'UNIVERS

Règles métier BusinessRules :

ZOOM1 (cible principale de PT2QE)

RCI PI (avec ou sans KAM)
  → ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'PINDEP'

RCI GI SANS KAM
  → ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GINDEP' AND ID_KAM = 'NO_KAM'

FG_HM = '1' pour RSI/RCI (hors RSC)
  → FG_HM = '1' AND (
      (ID_TC_CG = 'RSI' AND ID_TC_CIBLE IN ('MP_AO_', 'GR_A_G', ...))
      OR (ID_TC_CG = 'RCI' AND ID_TC_CIBLE IN ('PERSYS', 'PERCLI', 'AS_AUT'))
    )

RSC avec ID_MERC_HM = 'HM'
  → ID_TC_CG = 'RSC' AND ID_TC_CIBLE IN ('CR_NAT', 'SRCNAT', ...)
    AND TRIM(ID_MERC_HM) = 'HM'

ZOOM2

RCI GI AVEC KAM
  → ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GINDEP' AND ID_KAM <> 'NO_KAM'

FG_HM = '0' pour RSI/RCI
  → FG_HM = '0' AND (
      (ID_TC_CG = 'RSI' AND ID_TC_CIBLE IN ('MP_AO_', 'SRCREG', ...))
      OR (ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GC_REG')
    )

RCI GC_REG avec FG_HM = '1'
  → ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GC_REG' AND FG_HM = '1'

ZOOM3

RSC avec ID_MERC_HM <> 'HM'
  → ID_TC_CG = 'RSC' AND ID_TC_CIBLE IN (...)
    AND TRIM(ID_MERC_HM) <> 'HM'

RCC
  → ID_TC_CG = 'RCC' AND ID_TC_CIBLE IN ('RCHNAT', 'GCN3PL', 'GCNDIR')

⚠️ Point d'attention : PT2QE applique un filtre strict WHERE UNIVERS = 'ZOOM1' après le calcul de l'UNIVERS. Les offres ZOOM2 et ZOOM3 sont exclues du traitement.

Phase 4 : Enrichissement des dimensions

Mapping TYPE_CLIENT

Table : PT0CE_TYPE_CLIENT_MAPPING
Jointure :

LEFT JOIN PT0CE_TYPE_CLIENT_MAPPING tc
  ON tc.UNIVERS = ou.UNIVERS
  AND tc.ID_TC_CG = ou.ID_TC_CG
  AND tc.ID_TC_CIBLE = ou.ID_TC_CIBLE
  AND tc.FG_HM = ou.FG_HM

Colonnes récupérées : - TYPE_CLIENT : Libellé normalisé (ex: "RCI PI GI", "RSI HM") - UNIVERS : Confirmation de l'univers calculé

Traitement des valeurs nulles :

COALESCE(tc.TYPE_CLIENT, 'Hors référentiel') AS TYPE_CLIENT

Mapping TYPE_RESTAURANT

Table : PT0CE_TYPE_RESTAURANT_MAPPING
Jointure :

LEFT JOIN PT0CE_TYPE_RESTAURANT_MAPPING tr
  ON tr.LC_SFC_CIBLE = ou.LC_SFC_CIBLE

Colonne récupérée : - Type_Restaurant : Classification de l'établissement

Traitement des valeurs nulles :

COALESCE(tr.Type_Restaurant, 'Hors référentiel') AS TYPE_RESTAURANT

Enrichissement GEO

Source : SYS_MD_CLIENT.LC_ZDV_GRV
Utilisation : Zone géographique pour le matching avec les corridors MASTER

Phase 5 : Enrichissement historique 4Q

Sous-requête : HISTORICAL_PERFORMANCE
Agrégation : Par ID_CLN et ID_ART

Métriques calculées : 1. CA global (hors promos) : - MT_CAB_4Q : Somme des CA sur 4 trimestres - QT_UF_4Q : Somme des quantités UF - QT_KG_4Q : Somme des quantités KG

  1. CA Prix Fermes :
  2. MT_CAB_4Q_FERMES : CA sur LC_PRP_N1 = 'Prix fermes'
  3. QT_UF_4Q_FERMES, QT_KG_4Q_FERMES

  4. CA Prix Indexés :

  5. MT_CAB_4Q_INDEXES : CA sur LC_PRP_N1 = 'Prix indexés'
  6. QT_UF_4Q_INDEXES, QT_KG_4Q_INDEXES

Valeurs par défaut :

NVL(hp.MT_CAB_4Q, 0) as MT_CAB_4Q

Phase 6 : Dernière QT_UF connue

Sous-requête : LAST_QT_UF
Objectif : Calculer le prix unitaire actuel

-- Dernière ligne de facture avec QT_UF > 0
ROW_NUMBER() OVER (
  PARTITION BY c.ID_CLN, f.ID_ART 
  ORDER BY f.DT_CDE DESC, f.ID_FAC DESC
)

-- Prix unitaire
PRIX_TARIF_ACTUEL as PRIX_UNITAIRE_ACTUEL

Valeur par défaut :

NVL(lq.LAST_QT_UF, 1) as LAST_QT_UF

Filtrage final ZOOM1

Clause WHERE finale :

WHERE ou.UNIVERS = 'ZOOM1'
  AND tc.TYPE_CLIENT IS NOT NULL
  AND tr.TYPE_RESTAURANT IS NOT NULL

Toutes les offres qui ne sont pas : - ZOOM1 explicitement - Mappées TYPE_CLIENT - Mappées TYPE_RESTAURANT

...sont exclues du processus PT2QE.


Matching avec les corridors PT1CE

Principe du matching en cascade

PT2QE utilise une approche fallback en 2 niveaux pour maximiser la couverture des offres :

  1. Tentative MASTER : Matching exact sur 4 dimensions
  2. Fallback NATIONAL : Si échec, matching sur l'article uniquement

Niveau 1 : Matching MASTER

Table de sortie : MATCH_MASTER (sous-requête)

Conditions de jointure :

LEFT JOIN CORRIDORS_ZOOM1_ONLY c
  ON o.ID_ART = c.ID_ART                          -- Article exact
  AND o.TYPE_CLIENT = c.TYPE_CLIENT               -- Type client exact
  AND o.TYPE_RESTAURANT = c.TYPE_RESTAURANT       -- Type restaurant exact
  AND NVL(o.GEO, 'NULL') = NVL(c.GEO, 'NULL')    -- Zone géo exacte
  AND c.CUBE_TYPE = 'MASTER'

Caractéristiques : - Corridor spécifique au contexte client - 4 dimensions de segmentation - Taux de matching typiquement 70-85% - Utilisé en priorité si disponible

Niveau 2 : Fallback NATIONAL

Table de sortie : MATCH_NATIONAL (sous-requête)

Conditions de jointure :

JOIN CORRIDORS_ZOOM1_ONLY c
  ON o.ID_ART = c.ID_ART                          -- Article uniquement
  AND c.TYPE_CLIENT = 'NATIONAL'
  AND c.TYPE_RESTAURANT = 'NATIONAL'
  AND (c.GEO = 'NATIONAL' OR c.GEO IS NULL)
  AND c.CUBE_TYPE = 'NATIONAL'
WHERE NOT EXISTS (
  -- Seulement si pas déjà matché MASTER
  SELECT 1 FROM MATCH_MASTER m 
  WHERE m.ID_CLN = o.ID_CLN AND m.ID_ART = o.ID_ART
)

Caractéristiques : - Corridor agrégé national (toutes transactions article confondues) - 1 seule dimension (ID_ART) - Utilisé pour nouveaux clients ou segments atypiques - Taux de matching sur le résidu : 10-20%

Niveau 3 : Offres sans corridor

Table de sortie : NO_MATCH (sous-requête)

Condition :

WHERE NOT EXISTS (SELECT 1 FROM MATCH_MASTER ...)
  AND NOT EXISTS (SELECT 1 FROM MATCH_NATIONAL ...)

Traitement : - Toutes les colonnes corridor = NULL - HAS_CORRIDOR = 0 - MATCH_TYPE = 'NO_MATCH' - Ces offres sont exclues du calcul de recommandations (filtre WHERE HAS_CORRIDOR = 1)

Colonnes récupérées depuis PT1CE

Anciennes bornes PT0CE (référence historique)

PAS_ACTIF               -- Prix d'achat standard actuel
PRB_RC_ACTIF            -- PRB Restauration Collective actuel
PRB_COLL_ACTIF          -- PRB Collectivité actuel
PRB_TO_USE              -- Flag indiquant quel PRB utiliser (1=RC, 0=COLL)
PRB_ACTIF               -- PRB calculé selon PRB_TO_USE

BORNE_PL1_PL2           -- Séparation PL1/PL2 ancienne
BORNE_PL2_PL3           -- Séparation PL2/PL3 ancienne
BORNE_PL3_PL4           -- Séparation PL3/PL4 ancienne
BORNE_PL4_PL5           -- Séparation PL4/PL5 ancienne
BORNE_PL5_PL6           -- Séparation PL5/PL6 ancienne
BORNE_PL6_PLX           -- Séparation PL6/PLX ancienne

Nouvelles bornes PT1CE (post-optimisation)

NEW_PAS                 -- Nouveau PAS recommandé par PT1CE
NEW_PRB_RC              -- Nouveau PRB RC
NEW_PRB_COLL            -- Nouveau PRB COLL
NEW_PRB                 -- Nouveau PRB calculé selon PRB_TO_USE

NEW_BORNE_PL1_PL2       -- Nouvelle séparation PL1/PL2
NEW_BORNE_PL2_PL3       -- ⭐ Utilisé comme PLANCHER dans CHEMIN 2
NEW_BORNE_PL3_PL4
NEW_BORNE_PL4_PL5
NEW_BORNE_PL5_PL6
NEW_BORNE_PL6_PLX

Métadonnées corridor

PRICE_SENSITIVITY       -- Sensibilité prix (HIGH/MEDIUM/LOW)
ECART_TYPE              -- Écart-type du corridor
CUBE_TYPE               -- MASTER ou NATIONAL
STATUS                  -- OPTIMAL (filtre appliqué)
SOURCE_ZOOM             -- ZOOM1/ZOOM2/ZOOM3

Calculs dérivés

PCT_HAUSSE_PAS          -- (NEW_PAS - PAS_ACTIF) / PAS_ACTIF
HAS_CORRIDOR            -- 1 si corridor trouvé, 0 sinon
MATCH_TYPE              -- MASTER / NATIONAL / NO_MATCH

Les deux logiques de recommandation

Recommandation 1 : Repositionnement par paliers

Principe

RECO1 analyse la position actuelle du prix dans le corridor et propose un repositionnement vers les bornes supérieures. L'objectif est de faire progresser les prix vers des paliers plus rémunérateurs.

Configuration des règles

Les règles de repositionnement sont paramétrables via le fichier config/pt2qe_config.json :

{
  "recommendations": {
    "reco1_rules": [
      {
        "position": "ABOVE_PL1",
        "condition": "PRIX_TARIF_ACTUEL > NEW_BORNE_PL1_PL2",
        "action": "NO_CHANGE",
        "target": "PRIX_TARIF_ACTUEL",
        "comment": "Prix déjà en PL1, pas de changement"
      },
      {
        "position": "PL1_PL2",
        "condition": "PRIX_TARIF_ACTUEL > NEW_BORNE_PL2_PL3",
        "action": "TO_PL1",
        "target": "NEW_BORNE_PL1_PL2",
        "comment": "Remonter vers PL1"
      },
      ...
    ]
  }
}

Structure d'une règle : - position : Nom de la position source - condition : Expression SQL de détection - action : Nom de l'action à effectuer - target : Colonne SQL cible pour le nouveau prix - comment : Documentation de la règle

Génération SQL dynamique

Le code Python (PT2QEConfig.build_reco1_sql_case()) génère automatiquement le CASE SQL depuis la configuration :

CASE
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL1_PL2 
    THEN ed.PRIX_TARIF_ACTUEL  -- Prix déjà en PL1
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL2_PL3 
    THEN ed.NEW_BORNE_PL1_PL2  -- Remonter vers PL1
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL3_PL4 
    THEN ed.NEW_BORNE_PL1_PL2  -- Remonter vers PL1
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL4_PL5 
    THEN ed.NEW_BORNE_PL2_PL3  -- Remonter vers PL2
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL5_PL6 
    THEN ed.NEW_BORNE_PL3_PL4  -- Remonter vers PL3
  WHEN ed.PRIX_TARIF_ACTUEL > ed.NEW_BORNE_PL6_PLX 
    THEN ed.NEW_BORNE_PL5_PL6  -- Remonter vers PL5
  WHEN ed.PRIX_TARIF_ACTUEL >= ed.NEW_PAS 
    THEN ed.NEW_BORNE_PL6_PLX  -- Remonter vers PL6
  ELSE ed.NEW_PAS  -- Remonter au PAS minimum
END as RECO1_BASE

Modification des règles de repositionnement

Pour changer la logique de repositionnement :

  1. Éditer le fichier : config/pt2qe_config.json
  2. Modifier la section : recommendations.reco1_rules
  3. Exemples de modifications possibles :
// Exemple 1 : Repositionnement plus agressif
// Au lieu de PL2→PL3 aller vers PL2→PL1
{
  "position": "PL2_PL3",
  "condition": "PRIX_TARIF_ACTUEL > NEW_BORNE_PL3_PL4",
  "action": "TO_PL1",           // ← Au lieu de TO_PL2
  "target": "NEW_BORNE_PL1_PL2",
  "comment": "Remonter directement vers PL1"
}

// Exemple 2 : Ajouter une règle intermédiaire
{
  "position": "PL3_MID",
  "condition": "PRIX_TARIF_ACTUEL > (NEW_BORNE_PL3_PL4 + NEW_BORNE_PL2_PL3) / 2",
  "action": "TO_PL2",
  "target": "NEW_BORNE_PL2_PL3",
  "comment": "Milieu de PL3 vers PL2"
}

// Exemple 3 : Repositionnement conservateur
// Ne remonter que d'un palier
{
  "position": "PL5_PL6",
  "condition": "PRIX_TARIF_ACTUEL > NEW_BORNE_PL6_PLX",
  "action": "TO_PL5",
  "target": "NEW_BORNE_PL5_PL6",  // ← Au lieu de PL4
  "comment": "Remonter seulement d'un palier"
}
  1. Relancer PT2QE : La nouvelle configuration sera chargée automatiquement au prochain run

⚠️ Attention : Les conditions doivent être mutuellement exclusives et triées de la plus restrictive à la moins restrictive.

Règles par défaut (sans configuration)

Si pt2qe_config.json est absent ou incomplet, PT2QE utilise les règles par défaut codées en dur dans PT2QEConfig._defaults.

Recommandation 2 : Hausse proportionnelle au PAS

Principe

RECO2 applique le même pourcentage de hausse que celui du PAS du corridor au prix actuel de l'offre.

Formule

RECO2 = PRIX_TARIF_ACTUEL × (1 + PCT_HAUSSE_PAS)

 :
PCT_HAUSSE_PAS = (NEW_PAS - PAS_ACTIF) / PAS_ACTIF

Exemple de calcul

Contexte corridor : - PAS ancien : 10,00 € - PAS nouveau : 11,00 € (+10%) - PCT_HAUSSE_PAS = 0,10

Application à une offre : - Prix tarif actuel : 15,00 € - RECO2 = 15,00 × 1,10 = 16,50 € - Hausse recommandée : +1,50 € (+10%)

Caractéristiques

Avantages : - Suit mécaniquement l'évolution des coûts d'achat - Simple et transparent - Proportionnel au prix existant

Inconvénients : - Ne repositionne pas dans le corridor - Peut rester dans des paliers bas - Moins agressif que RECO1 en général


Arbre de décision à 3 chemins

Vue d'ensemble

PT2QE n'applique pas systématiquement la logique MAX(RECO1, RECO2). Le prix final dépend d'un arbre de décision qui analyse le contexte de chaque offre.

                    ┌─────────────────┐
                    │  Offre de prix  │
                    └────────┬────────┘
                ┌────────────▼────────────┐
                │  NEW_PAS < PAS_ACTIF ?  │
                └────────┬───────┬────────┘
                         │ OUI   │ NON
                         │       │
            ┌────────────▼       └───────────────┐
            │ CHEMIN 1            │                │
            │ GEL PRIX            │                │
            │ Prix = Actuel       │                │
            └─────────────────────┘                │
                                        ┌──────────▼──────────┐
                                        │ Prix dans PL1       │
                                        │ anciennes bornes ?  │
                                        └──────┬─────┬────────┘
                                               │ OUI │ NON
                                               │     │
                                  ┌────────────▼     └────────────┐
                                  │ CHEMIN 2                      │
                                  │ CONSERVATION PREMIUM          │
                                  │ Prix + Plancher               │
                                  └───────────────────────────────┘
                                                      ┌────────────▼────────────┐
                                                      │ CHEMIN 3                │
                                                      │ OPTIMISATION STANDARD   │
                                                      │ MAX(RECO1, RECO2)       │
                                                      └─────────────────────────┘

CHEMIN 1 : PAS_BAISSE_GEL_PRIX

Condition de déclenchement

DECISION_PATH = 'PAS_BAISSE_GEL_PRIX'
WHERE NEW_PAS < PAS_ACTIF

Détection : - Le nouveau PAS recommandé par PT1CE est inférieur au PAS actif - Indique une baisse du coût d'achat

Logique de calcul

PRIX_RECOMMANDE = PRIX_TARIF_ACTUEL
PCT_HAUSSE_FINALE = 0
RECO_SELECTIONNEE = 'GEL_PRIX'
CAPPING_APPLIED = 'GEL_PAS'

Principe : - Le prix reste strictement inchangé - Aucune recommandation n'est calculée (RECO1 et RECO2 sont calculées mais ignorées) - Pas de hausse appliquée (0%)

Rationale métier

Pourquoi geler le prix en cas de baisse PAS ? - Ne pas répercuter les baisses de coût au client - Conserver la marge dégagée - Éviter un effet yo-yo tarifaire - Maintenir une perception de stabilité prix

Exemple :

Corridor avant PT1CE :
  PAS_ACTIF = 12,00 €
  PRIX_TARIF_ACTUEL = 18,00 €
  Marge = 6,00 €

Corridor après PT1CE :
  NEW_PAS = 11,00 € (baisse de 1€)

→ CHEMIN 1 déclenché
→ PRIX_RECOMMANDE = 18,00 € (inchangé)
→ Nouvelle marge = 7,00 € (+1€)

CHEMIN 2 : PL1_CONSERVATION_PREMIUM

Conditions de déclenchement

DECISION_PATH = 'PL1_CONSERVATION_PREMIUM'
WHERE NEW_PAS >= PAS_ACTIF  -- Pas de baisse PAS
  AND PRIX_TARIF_ACTUEL <= PRB_ACTIF  -- Prix dans anciennes bornes
  AND PRIX_TARIF_ACTUEL > BORNE_PL1_PL2  -- Position PL1

Détection : - Le prix actuel est dans le PL1 des anciennes bornes (bornes PT0CE) - Clients "premium" facturés au niveau le plus élevé du corridor historique - Le PAS ne baisse pas (sinon CHEMIN 1 prioritaire)

Logique de calcul

-- Étape 1 : Conservation du prix actuel
PRIX_BASE = PRIX_TARIF_ACTUEL

-- Étape 2 : Application plancher PL2_PL3
PRIX_AVEC_PLANCHER = GREATEST(PRIX_BASE, NEW_BORNE_PL2_PL3)

-- Étape 3 : Application capping PRB final
PRIX_RECOMMANDE = LEAST(PRIX_AVEC_PLANCHER, NEW_PRB)

-- Métadonnées
RECO_SELECTIONNEE = 'CONSERVATION_PREMIUM'
CAPPING_APPLIED = CASE
  WHEN PRIX_AVEC_PLANCHER > NEW_PRB THEN 'PRB_FINAL'
  WHEN PRIX_BASE < NEW_BORNE_PL2_PL3 THEN 'PLANCHER_PL2_PL3'
  ELSE 'NONE'
END

Plancher de sécurité PL2_PL3

Objectif : Protéger contre la compression du corridor

Mécanisme :

PRIX_FINAL = MAX(PRIX_ACTUEL, NEW_BORNE_PL2_PL3)

Scénario d'activation :

Anciennes bornes :
  PL1_PL2 = 22,00 €
  PRIX_ACTUEL = 23,00 € (en PL1)

Nouvelles bornes (après recalibrage PT1CE) :
  NEW_PL1_PL2 = 24,00 € (hausse)
  NEW_PL2_PL3 = 20,00 €

Sans plancher :
  PRIX_FINAL = 23,00 € (inchangé)
  → Passe de PL1 (anciennes) à PL2 (nouvelles)
  → Dégradation relative

Avec plancher :
  PRIX_FINAL = MAX(23,00 ; 20,00) = 23,00 €
  → Reste à 23,00 € (aucun changement nécessaire ici)

Cas extrême :
  NEW_PL2_PL3 = 25,00 € (forte compression)
  → PRIX_FINAL = MAX(23,00 ; 25,00) = 25,00 €
  → Remontée forcée pour rester dans PL2

Flag de détection :

PLANCHER_PL2_APPLIED = CASE
  WHEN PRIX_ACTUEL < NEW_BORNE_PL2_PL3 THEN 1
  ELSE 0
END

Capping PRB final

Comme tous les chemins, le CHEMIN 2 applique le capping PRB en dernière étape :

PRIX_RECOMMANDE = LEAST(PRIX_AVEC_PLANCHER, NEW_PRB)

Ce capping peut s'appliquer si : - Le corridor s'est fortement compressé (écart PAS-PRB réduit) - Le plancher PL2_PL3 a remonté le prix au-dessus du PRB

Rationale métier

Pourquoi conserver les clients premium ? - Maintenir les clients les mieux valorisés en position haute - Éviter un effet de "décalibrage" suite à l'optimisation PT1CE - Le plancher PL2_PL3 assure qu'ils ne descendent pas trop dans le nouveau corridor - Priorité à la stabilité relationnelle sur l'optimisation tarifaire agressive

Exemple complet :

Avant PT1CE :
  PRB_ACTIF = 25,00 €
  BORNE_PL1_PL2 = 22,00 €
  PRIX_ACTUEL = 24,00 € (en PL1, bien valorisé)

Après PT1CE :
  NEW_PRB = 26,00 €
  NEW_BORNE_PL1_PL2 = 23,50 €
  NEW_BORNE_PL2_PL3 = 21,00 €

→ CHEMIN 2 déclenché
→ PRIX_BASE = 24,00 € (conservation)
→ PLANCHER = MAX(24,00 ; 21,00) = 24,00 € (pas d'effet)
→ PRIX_RECOMMANDE = MIN(24,00 ; 26,00) = 24,00 €
→ PCT_HAUSSE_FINALE = 0% (stabilité totale)

CHEMIN 3 : OPTIMISATION_STANDARD

Condition de déclenchement

DECISION_PATH = 'OPTIMISATION_STANDARD'
WHERE NEW_PAS >= PAS_ACTIF  -- Pas de baisse PAS
  AND NOT (
    PRIX_TARIF_ACTUEL <= PRB_ACTIF 
    AND PRIX_TARIF_ACTUEL > BORNE_PL1_PL2
  )  -- Pas en PL1 anciennes

Détection : - Tous les cas qui ne sont ni CHEMIN 1 ni CHEMIN 2 - Représente la majorité des offres (70-90%) - Cas "standard" d'optimisation tarifaire

Cascade de capping (ordre d'application)

Le CHEMIN 3 applique une cascade de capping en 3 étapes avant la sélection finale :

RECO1_BASE (repositionnement brut)
[ÉTAPE 1] Capping sensibilité prix
RECO1_APRES_CAPPING_SENSIBILITE
[ÉTAPE 2] Capping basiques (50% max)
RECO1_AVEC_CAPPING (finale)
[SÉLECTION] MAX(RECO1_AVEC_CAPPING, RECO2)
[ÉTAPE 3] Capping PRB final
PRIX_RECOMMANDE

ÉTAPE 1 : Capping sensibilité prix

Objectif : Limiter les hausses selon la sensibilité du produit

Mécanisme :

RECO1_APRES_CAPPING_SENSIBILITE = CASE
  WHEN PRICE_SENSITIVITY = 'HIGH' AND CAPPING_HIGH IS NOT NULL THEN
    LEAST(RECO1_BASE, PRIX_TARIF_ACTUEL * (1 + CAPPING_HIGH))
  WHEN PRICE_SENSITIVITY = 'MEDIUM' AND CAPPING_MEDIUM IS NOT NULL THEN
    LEAST(RECO1_BASE, PRIX_TARIF_ACTUEL * (1 + CAPPING_MEDIUM))
  WHEN PRICE_SENSITIVITY = 'LOW' AND CAPPING_LOW IS NOT NULL THEN
    LEAST(RECO1_BASE, PRIX_TARIF_ACTUEL * (1 + CAPPING_LOW))
  ELSE RECO1_BASE
END

Taux par défaut (fichier inputs/capping_type_client.csv) : - CAPPING_HIGH = 0,025 (2,5% maximum) - CAPPING_MEDIUM = 0,05 (5% maximum) - CAPPING_LOW = 0,075 (7,5% maximum)

Exemple :

PRIX_ACTUEL = 20,00 €
RECO1_BASE = 24,00 € (+20%)
PRICE_SENSITIVITY = HIGH
CAPPING_HIGH = 0,025

→ Prix max avec capping = 20,00 × 1,025 = 20,50 €
→ RECO1_APRES_CAPPING_SENSIBILITE = MIN(24,00 ; 20,50) = 20,50 €
→ Capping actif (ramène de +20% à +2,5%)

Modification des cappings sensibilité :

Pour ajuster les taux par TYPE_CLIENT :

  1. Éditer : inputs/capping_type_client.csv
  2. Format :

    TYPE_CLIENT;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
    RCI PI GI;0,025;0,05;0,075
    RSI HM;0,020;0,045;0,070
    RSC HM;0,030;0,055;0,080
    

  3. Relancer PT2QE : Les nouveaux taux seront appliqués

ÉTAPE 2 : Capping basiques (50% max)

Objectif : Limiter les hausses excessives sur les produits de base

Mécanisme :

RECO1_AVEC_CAPPING = CASE
  WHEN LC_ATTRIBUT = 'Basiques' THEN
    LEAST(
      RECO1_APRES_CAPPING_SENSIBILITE,
      PRIX_TARIF_ACTUEL * 1.50
    )
  ELSE RECO1_APRES_CAPPING_SENSIBILITE
END

Comportement : - S'applique uniquement si LC_ATTRIBUT = 'Basiques' - Vient APRÈS le capping sensibilité - Écrase le capping sensibilité si plus restrictif

Exemple cascade complète :

PRIX_ACTUEL = 10,00 €
RECO1_BASE = 18,00 € (+80%)
PRICE_SENSITIVITY = LOW
CAPPING_LOW = 0,075 (7,5%)
LC_ATTRIBUT = 'Basiques'

→ ÉTAPE 1 : Capping sensibilité
  Prix max = 10,00 × 1,075 = 10,75 €
  RECO1_APRES_CAPPING = MIN(18,00 ; 10,75) = 10,75 €

→ ÉTAPE 2 : Capping basiques
  Prix max basiques = 10,00 × 1,50 = 15,00 €
  RECO1_AVEC_CAPPING = MIN(10,75 ; 15,00) = 10,75 €
  → Pas d'effet (sensibilité plus restrictive)

Autre exemple :
PRIX_ACTUEL = 10,00 €
RECO1_BASE = 18,00 € (+80%)
PRICE_SENSITIVITY = LOW
CAPPING_LOW = 0,20 (20%)
LC_ATTRIBUT = 'Basiques'

→ ÉTAPE 1 : Capping sensibilité
  Prix max = 10,00 × 1,20 = 12,00 €
  RECO1_APRES_CAPPING = MIN(18,00 ; 12,00) = 12,00 €

→ ÉTAPE 2 : Capping basiques
  Prix max basiques = 10,00 × 1,50 = 15,00 €
  RECO1_AVEC_CAPPING = MIN(12,00 ; 15,00) = 12,00 €
  → Pas d'effet (sensibilité plus restrictive)

Cas où basiques s'applique :
PRIX_ACTUEL = 10,00 €
RECO1_BASE = 22,00 € (+120%)
PRICE_SENSITIVITY = NULL (pas de capping sensibilité)
LC_ATTRIBUT = 'Basiques'

→ ÉTAPE 1 : Pas de capping
  RECO1_APRES_CAPPING = 22,00 €

→ ÉTAPE 2 : Capping basiques
  Prix max basiques = 10,00 × 1,50 = 15,00 €
  RECO1_AVEC_CAPPING = MIN(22,00 ; 15,00) = 15,00 €
  → Capping actif (ramène de +120% à +50%)

Modification du seuil basiques :

Le taux de 50% est codé en dur dans la requête SQL et dans PT2QEConfig._defaults['capping']['basiques'].

Pour le modifier : 1. Éditer : config/pt2qe_config.json 2. Section :

{
  "capping": {
    "basiques": 0.60
  }
}
3. Limitation : La modification du fichier JSON n'a pas d'effet sur la requête SQL actuelle. Il faudrait modifier le code SQL dans calculate_recommandations.py :

-- Ligne à modifier (apparaît plusieurs fois)
r.PRIX_TARIF_ACTUEL * 1.50  -- Changer 1.50 en 1.60 pour 60%

SÉLECTION : MAX(RECO1_AVEC_CAPPING, RECO2)

Mécanisme :

PRIX_AVANT_CAPPING_PRB = GREATEST(RECO1_AVEC_CAPPING, RECO2)

RECO_TYPE = CASE
  WHEN RECO1_AVEC_CAPPING >= RECO2 THEN 'REPOSITIONNEMENT_PALIERS'
  ELSE 'HAUSSE_PROPORTIONNELLE_PAS'
END

RECO_SELECTIONNEE = CASE
  WHEN RECO1_AVEC_CAPPING >= RECO2 THEN 'RECO1_REPOSITIONNEMENT_PALIERS'
  ELSE 'RECO2_HAUSSE_PROPORTIONNELLE_PAS'
END

Principes : - RECO1 est privilégiée en cas d'égalité - RECO2 n'est pas cappée (suit mécaniquement le PAS) - La cascade de capping ne s'applique qu'à RECO1

Exemple de sélection :

Cas A : RECO1 gagne
  RECO1_AVEC_CAPPING = 18,00 €
  RECO2 = 17,50 €
  → PRIX_AVANT_PRB = 18,00 €
  → RECO_SELECTIONNEE = RECO1_REPOSITIONNEMENT_PALIERS

Cas B : RECO2 gagne
  RECO1_AVEC_CAPPING = 16,00 €
  RECO2 = 17,50 €
  → PRIX_AVANT_PRB = 17,50 €
  → RECO_SELECTIONNEE = RECO2_HAUSSE_PROPORTIONNELLE_PAS

Cas C : Égalité
  RECO1_AVEC_CAPPING = 17,50 €
  RECO2 = 17,50 €
  → PRIX_AVANT_PRB = 17,50 €
  → RECO_SELECTIONNEE = RECO1_REPOSITIONNEMENT_PALIERS (priorité)

ÉTAPE 3 : Capping PRB final

Objectif : Garantir que le prix ne dépasse jamais le PRB

Mécanisme :

PRIX_RECOMMANDE = LEAST(PRIX_AVANT_CAPPING_PRB, NEW_PRB)

CAPPING_PRB_APPLIED = CASE
  WHEN PRIX_AVANT_CAPPING_PRB > NEW_PRB THEN 1
  ELSE 0
END

Application : - S'applique à TOUS les chemins (1, 2, 3) - Vient en dernière étape (capping ultime) - Protège contre la compression du corridor

Exemple :

RECO1_AVEC_CAPPING = 22,00 €
RECO2 = 21,50 €
NEW_PRB = 20,00 €

→ PRIX_AVANT_PRB = MAX(22,00 ; 21,50) = 22,00 €
→ PRIX_RECOMMANDE = MIN(22,00 ; 20,00) = 20,00 €
→ CAPPING_PRB_APPLIED = 1
→ CAPPING_APPLIED = 'PRB_FINAL'

Synthèse du capping appliqué

Colonne : CAPPING_APPLIED

Ordre de priorité (du plus contraignant au moins) : 1. GEL_PAS : Gel total (CHEMIN 1) 2. PRB_FINAL : Plafond PRB absolu 3. PLANCHER_PL2_PL3 : Plancher de sécurité (CHEMIN 2) 4. BASIQUES_50PCT : Capping basiques à +50% 5. SENSIBILITE : Capping selon sensibilité prix 6. NONE : Aucun capping appliqué

Logique de détermination :

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

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

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

  -- Priorité 4 : Capping basiques
  WHEN CAPPING_BASIQUES_APPLIED = 1 THEN 'BASIQUES_50PCT'

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

  -- Aucun capping
  ELSE 'NONE'
END

Exemple de détermination :

Cas 1 : Capping sensibilité ET capping PRB actifs
→ CAPPING_APPLIED = 'PRB_FINAL' (priorité 2 > priorité 5)

Cas 2 : Capping sensibilité ET capping basiques actifs
→ CAPPING_APPLIED = 'BASIQUES_50PCT' (priorité 4 > priorité 5)
→ Note : En pratique, si basiques s'applique, c'est qu'il est plus restrictif
          que sensibilité, donc basiques a bien agi

Cas 3 : Seulement capping sensibilité actif
→ CAPPING_APPLIED = 'SENSIBILITE'

Cas 4 : Aucun capping actif
→ CAPPING_APPLIED = 'NONE'


Les 3 positions du prix

Philosophie

PT2QE calcule et expose 3 positions pour chaque offre, permettant de tracer l'évolution du prix à travers les différentes étapes du processus de pricing.

Position 1 : Prix actuel dans ANCIENNES bornes

Colonne : POSITION_TARIF_ACTUEL_DANS_ANCIENNES_BORNES

Référentiel : Bornes PT0CE (pré-optimisation)

Calcul :

CASE
  WHEN PRIX_TARIF_ACTUEL > PRB_ACTIF THEN 'ABOVE_PRB'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL1_PL2 THEN 'PL1'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL2_PL3 THEN 'PL2'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL3_PL4 THEN 'PL3'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL4_PL5 THEN 'PL4'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL5_PL6 THEN 'PL5'
  WHEN PRIX_TARIF_ACTUEL >= BORNE_PL6_PLX THEN 'PL6'
  WHEN PRIX_TARIF_ACTUEL >= PAS_ACTIF THEN 'PLX'
  ELSE 'BELOW_PAS'
END

Utilité : - Point de départ historique - Sert à détecter les clients PL1 (CHEMIN 2) - Permet de mesurer l'évolution post-optimisation

Position 2 : Prix actuel dans NOUVELLES bornes

Colonne : PALIER_TARIF_ACTUEL_VS_NOUVELLES_BORNES

Référentiel : Bornes PT1CE (post-optimisation)

Calcul :

CASE
  WHEN PRIX_TARIF_ACTUEL > NEW_PRB THEN 'ABOVE_PRB'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL1_PL2 THEN 'PL1'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL2_PL3 THEN 'PL2'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL3_PL4 THEN 'PL3'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL4_PL5 THEN 'PL4'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL5_PL6 THEN 'PL5'
  WHEN PRIX_TARIF_ACTUEL >= NEW_BORNE_PL6_PLX THEN 'PL6'
  WHEN PRIX_TARIF_ACTUEL >= NEW_PAS THEN 'PLX'
  ELSE 'BELOW_PAS'
END

Utilité : - Montre l'impact du recalibrage PT1CE - Un prix peut changer de palier sans bouger (corridor déplacé) - Base pour calculer RECO1

Position 3 : Prix recommandé dans NOUVELLES bornes

Colonne : POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES

Référentiel : Bornes PT1CE (post-optimisation)

Calcul :

CASE
  WHEN PRIX_RECOMMANDE > NEW_PRB THEN 'ABOVE_PRB'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL1_PL2 THEN 'PL1'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL2_PL3 THEN 'PL2'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL3_PL4 THEN 'PL3'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL4_PL5 THEN 'PL4'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL5_PL6 THEN 'PL5'
  WHEN PRIX_RECOMMANDE >= NEW_BORNE_PL6_PLX THEN 'PL6'
  WHEN PRIX_RECOMMANDE >= NEW_PAS THEN 'PLX'
  ELSE 'BELOW_PAS'
END

Utilité : - Objectif atteint par PT2QE - Mesure l'efficacité du repositionnement - Permet de valider la cohérence des recommandations

Exemple de trajectoire

Offre client A - article X

POSITION 1 (anciennes bornes) : PL3
  PRB_ACTIF = 25,00 €
  BORNE_PL2_PL3 = 20,00 €
  BORNE_PL3_PL4 = 15,00 €
  PRIX_ACTUEL = 18,00 €
  → Entre PL3_PL4 et PL2_PL3 = PL3

POSITION 2 (nouvelles bornes, prix inchangé) : PL4
  NEW_PRB = 27,00 €
  NEW_BORNE_PL3_PL4 = 19,00 € (hausse de 4€)
  NEW_BORNE_PL4_PL5 = 14,00 €
  PRIX_ACTUEL = 18,00 € (inchangé)
  → Entre PL4_PL5 et PL3_PL4 = PL4
  → Décalibrage : passe de PL3 à PL4 sans bouger

POSITION 3 (après recommandation PT2QE) : PL2
  RECO1_BASE = 22,00 € (objectif PL2_PL3 = 21,00 €)
  RECO1_AVEC_CAPPING = 19,80 € (capping sensibilité)
  RECO2 = 19,26 € (hausse PAS +7%)
  PRIX_RECOMMANDE = MAX(19,80 ; 19,26) = 19,80 €
  → Entre PL2_PL3 et PL1_PL2 = PL2
  → Repositionnement réussi : de PL4 à PL2

SYNTHÈSE :
  PL3 (anciennes) → PL4 (nouvelles, recalibrage) → PL2 (optimisation)
  18,00 € → 18,00 € → 19,80 € (+10%)

Valeurs possibles

Toutes les positions utilisent le même référentiel de valeurs :

  • ABOVE_PRB : Prix au-dessus du PRB (anormal)
  • PL1 : Palier 1 (meilleure valorisation)
  • PL2 : Palier 2
  • PL3 : Palier 3
  • PL4 : Palier 4
  • PL5 : Palier 5
  • PL6 : Palier 6
  • PLX : Palier X (entre PAS et PL6)
  • BELOW_PAS : En dessous du PAS (anormal)

Ajustement des cappings (Étape optionnelle)

Principe

Après avoir généré une première série de recommandations, l'utilisateur peut affiner les cappings par cube (combinaison UNIVERS × TYPE_CLIENT × TYPE_RESTAURANT × GEO) et relancer le calcul.

Workflow d'ajustement

Run initial
Génération capping_cubes_generated.csv
Analyse des impacts
Décision d'ajustement ?
    ├─ OUI → Copier/renommer en capping_cubes_corrections.csv
    │         Modifier les valeurs
    │         Lancer 2_ajuster_cappings.bat
    │         Revenir à "Analyse des impacts"
    └─ NON → Passer à la génération finale

Fichier capping_cubes_generated.csv

Génération : Automatique lors du calcul des recommandations

Emplacement : outputs/run_YYYYMMDD_HHMMSS/capping_cubes_generated.csv

Structure :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;TRADITIONNEL;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075
ZOOM1;RCI PI GI;RESTAURATION_RAPIDE;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075
ZOOM1;NATIONAL;NATIONAL;NATIONAL;NATIONAL;0,03;0,10;0,15

Contenu : - Tous les cubes MASTER trouvés dans les offres - Un cube NATIONAL par univers (pour le fallback) - Cappings initiaux depuis capping_type_client.csv

Création du fichier de corrections

Étape 1 : Copier le fichier généré

cp outputs/run_20251103_143022/capping_cubes_generated.csv corrections/capping_cubes_corrections.csv

Étape 2 : Éditer avec Excel/LibreOffice - Garder la structure intacte (colonnes identiques) - Modifier uniquement les valeurs de capping souhaitées - Possibilité de ne modifier que certains cubes

Étape 3 : Sauvegarder au format CSV avec : - Séparateur : ; (point-virgule) - Décimales : , (virgule) - Encodage : cp1252 (Windows ANSI)

Exemples de modifications

Cas 1 : Assouplir un segment spécifique

Contexte : TYPE_CLIENT "RSI HM" avec hausses trop faibles

Avant :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RSI HM;TRADITIONNEL;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075

Après :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RSI HM;TRADITIONNEL;ILE-DE-FRANCE;MASTER;0,04;0,07;0,10

Effet : - HIGH : 2,5% → 4% (+60% de flexibilité) - MEDIUM : 5% → 7% (+40%) - LOW : 7,5% → 10% (+33%)

Cas 2 : Durcir un segment sensible

Contexte : TYPE_CLIENT "RCI PI GI" en zone rurale, hausses trop agressives

Avant :

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

Après :

UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CUBE_TYPE;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;RESTAURATION_RAPIDE;ZONE_RURALE;MASTER;0,015;0,03;0,05

Effet : - HIGH : 2,5% → 1,5% (-40% de flexibilité) - MEDIUM : 5% → 3% (-40%) - LOW : 7,5% → 5% (-33%)

Cas 3 : Différencier par TYPE_RESTAURANT

Contexte : RESTAURATION_RAPIDE peut accepter des hausses plus fortes

Avant :

ZOOM1;RCI PI GI;TRADITIONNEL;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075
ZOOM1;RCI PI GI;RESTAURATION_RAPIDE;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075

Après :

ZOOM1;RCI PI GI;TRADITIONNEL;ILE-DE-FRANCE;MASTER;0,025;0,05;0,075
ZOOM1;RCI PI GI;RESTAURATION_RAPIDE;ILE-DE-FRANCE;MASTER;0,035;0,065;0,095

Effet : Restauration rapide accepte ~30% de hausses en plus

Application des corrections

Commande :

2_ajuster_cappings.bat

Ou via le menu :

START.bat → Option 2

Paramètres implicites : - --skip-extraction : Ne réextrait pas les offres (utilise tables existantes) - --apply-corrections : Active le mode corrections - --corrections-folder corrections : Lit depuis le dossier corrections

Comportement :

  1. Lecture des tables existantes :
  2. PT2QE_PRICE_OFFERS (offres extraites lors du run initial)
  3. PT2QE_PRICE_OFFERS_ENRICHED (jointure corridors existante)

  4. Upload des corrections :

  5. Création table temporaire TEMP_CAPPING_CORRECTIONS
  6. Upload du CSV ligne par ligne

  7. Recalcul complet :

  8. Génération nouvelle table PT2QE_CAPPING_CUBES (écrase l'ancienne)
  9. Recalcul PT2QE_RECOMMENDATIONS avec nouveaux cappings
  10. Conservation de l'arbre de décision (DECISION_PATH inchangé)
  11. Recalcul de la cascade de capping avec nouveaux paramètres

  12. Nouvelle génération d'analyses :

  13. Tous les CSV sont régénérés dans outputs/corrections_YYYYMMDD_HHMMSS/
  14. capping_cubes_generated.csv reflète les nouvelles valeurs

Logique de mise à jour

Requête MERGE (dans apply_capping_rules.py) :

MERGE INTO PT2QE_RECOMMENDATIONS r
USING (SELECT * FROM TEMP_CAPPING_CORRECTIONS) c
ON (
  r.UNIVERS = c.UNIVERS
  AND r.TYPE_CLIENT = c.TYPE_CLIENT
  AND r.TYPE_RESTAURANT = c.TYPE_RESTAURANT
  AND NVL(r.GEO, 'NULL') = NVL(c.GEO, 'NULL')
)
WHEN MATCHED THEN UPDATE SET
  -- Recalcul RECO1_APRES_CAPPING_SENSIBILITE
  r.RECO1_APRES_CAPPING_SENSIBILITE = CASE
    WHEN r.PRICE_SENSITIVITY = 'HIGH' AND c.CAPPING_HIGH IS NOT NULL THEN
      LEAST(r.RECO1_BASE, r.PRIX_TARIF_ACTUEL * (1 + c.CAPPING_HIGH))
    WHEN r.PRICE_SENSITIVITY = 'MEDIUM' AND c.CAPPING_MEDIUM IS NOT NULL THEN
      LEAST(r.RECO1_BASE, r.PRIX_TARIF_ACTUEL * (1 + c.CAPPING_MEDIUM))
    WHEN r.PRICE_SENSITIVITY = 'LOW' AND c.CAPPING_LOW IS NOT NULL THEN
      LEAST(r.RECO1_BASE, r.PRIX_TARIF_ACTUEL * (1 + c.CAPPING_LOW))
    ELSE r.RECO1_BASE
  END,

  -- Recalcul RECO1_AVEC_CAPPING (avec basiques)
  r.RECO1_AVEC_CAPPING = CASE
    WHEN r.LC_ATTRIBUT = 'Basiques' THEN
      LEAST(
        [RECO1_APRES_CAPPING_SENSIBILITE avec nouveaux cappings],
        r.PRIX_TARIF_ACTUEL * 1.50
      )
    ELSE [RECO1_APRES_CAPPING_SENSIBILITE avec nouveaux cappings]
  END,

  -- Recalcul PRIX_RECOMMANDE selon DECISION_PATH
  r.PRIX_RECOMMANDE = CASE
    WHEN r.DECISION_PATH = 'PAS_BAISSE_GEL_PRIX' THEN r.PRIX_TARIF_ACTUEL
    WHEN r.DECISION_PATH = 'PL1_CONSERVATION_PREMIUM' THEN
      LEAST(GREATEST(r.PRIX_TARIF_ACTUEL, r.NEW_BORNE_PL2_PL3), r.NEW_PRB)
    WHEN r.DECISION_PATH = 'OPTIMISATION_STANDARD' THEN
      LEAST(GREATEST([RECO1_AVEC_CAPPING recalculée], r.RECO2), r.NEW_PRB)
  END,

  -- Recalcul PCT_HAUSSE_FINALE
  r.PCT_HAUSSE_FINALE = [formule selon DECISION_PATH],

  -- Recalcul POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES
  r.POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES = [CASE paliers],

  -- Recalcul CAPPING_APPLIED
  r.CAPPING_APPLIED = [logique de priorité],

  -- Recalcul RECO_SELECTIONNEE
  r.RECO_SELECTIONNEE = [selon RECO1 vs RECO2],

  -- Update timestamp
  r.CALCULATION_DATE = SYSDATE

Points clés : - RECO1_BASE et RECO2 ne changent pas (recalcul inutile) - DECISION_PATH ne change pas (contexte identique) - Seule la cascade de capping est recalculée - PRIX_RECOMMANDE est recalculé avec les nouvelles contraintes

Itérations successives

L'utilisateur peut effectuer plusieurs cycles d'ajustement :

Run 1 → capping_cubes_generated.csv → Analyse
Corrections A → Run 2 → capping_cubes_generated.csv (v2) → Analyse
Corrections B → Run 3 → capping_cubes_generated.csv (v3) → Analyse
Validation → Génération finale

Traçabilité : - Chaque run génère un dossier horodaté - corrections_YYYYMMDD_HHMMSS vs run_YYYYMMDD_HHMMSS - Possibilité de comparer les versions

Cas d'usage typiques

Scénario 1 : Convergence progressive

Objectif : Atteindre une hausse moyenne de 5%

Run 1 : Hausse moyenne 3,2% → Assouplir les cappings de 10%

Run 2 : Hausse moyenne 4,1% → Assouplir encore de 8%

Run 3 : Hausse moyenne 5,0% → Validation

Scénario 2 : Segmentation fine

Objectif : Différencier ILE-DE-FRANCE vs PROVINCE

Run 1 : Cappings uniformes → Identifier les écarts de comportement

Run 2 : Assouplir PROVINCE de 15% → Analyser les distributions

Run 3 : Ajuster ILE-DE-FRANCE à la baisse de 5% → Validation

Scénario 3 : Protection segments sensibles

Objectif : Limiter l'impact sur RSI HM

Run 1 : Hausse RSI HM = 4,8% (trop fort) → Durcir cappings RSI HM de 30%

Run 2 : Hausse RSI HM = 3,2% (acceptable) → Validation


Exports et analyses

Vue d'ensemble des exports

PT2QE génère 6 fichiers CSV à chaque run, permettant une analyse multi-angles des recommandations.

Emplacement : - Run initial : outputs/run_YYYYMMDD_HHMMSS/ - Après corrections : outputs/corrections_YYYYMMDD_HHMMSS/ - Génération finale : outputs/final_YYYYMMDD_HHMMSS/

Format commun : - Séparateur : ; (point-virgule) - Décimales : , (virgule) - Encodage : cp1252 (Windows ANSI) - Compatible Excel/LibreOffice

Export 1 : recommendations_detail.csv

Objectif : Ligne à ligne, traçabilité complète de chaque recommandation

Tri : Par PCT_HAUSSE_FINALE DESC (hausses les plus fortes en haut)

Colonnes principales :

Identifiants :

ID_CLN, LC_CLN          -- Client
ID_ART, LC_ART          -- Article
ID_CND                  -- Condition
DT_DEB_CONDITION, DT_FIN_CONDITION

Catégories produit :

CATEGORIE_N1            -- Hiérarchie N1 (ex: ALIMENTAIRE)
CATEGORIE_N2            -- Hiérarchie N2 (ex: EPICERIE)
CATEGORIE_N3            -- Hiérarchie N3 (ex: CONSERVES)
CATEGORIE_N4, N5, N6    -- Niveaux détaillés
MARQUE                  -- Marque article
LC_ATTRIBUT             -- Attribut (ex: Basiques, Premium)

Dimensions commerciales :

TYPE_CLIENT             -- Segment client (ex: RCI PI GI)
TYPE_RESTAURANT         -- Type établissement
GEO                     -- Zone géographique
UNIVERS                 -- ZOOM1/ZOOM2/ZOOM3
MATCH_TYPE              -- MASTER / NATIONAL / NO_MATCH

Métriques historiques 4Q :

MT_CAB_4Q               -- CA total hors promos
QT_UF_4Q, QT_KG_4Q      -- Volumes UF et KG
MT_CAB_4Q_FERMES        -- CA sur prix fermes
QT_UF_4Q_FERMES, QT_KG_4Q_FERMES
MT_CAB_4Q_INDEXES       -- CA sur prix indexés
QT_UF_4Q_INDEXES, QT_KG_4Q_INDEXES

Prix et positions :

PRIX_TARIF_ACTUEL       -- Prix actuel de l'offre
PRIX_UNITAIRE_ACTUEL    -- Prix actuel / QT_UF

-- Position 1 : Prix actuel dans anciennes bornes
POSITION_TARIF_ACTUEL_DANS_ANCIENNES_BORNES

-- Position 2 : Prix actuel dans nouvelles bornes
PALIER_TARIF_ACTUEL_VS_NOUVELLES_BORNES

-- Position 3 : Prix recommandé dans nouvelles bornes
POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES

Cascade de calcul :

PRICE_SENSITIVITY       -- HIGH / MEDIUM / LOW

RECO1_BASE              -- Repositionnement brut
RECO1_APRES_CAPPING_SENSIBILITE  -- Après étape 1 capping
RECO1_AVEC_CAPPING      -- Après cascade complète

RECO2                   -- Hausse proportionnelle PAS

Décision finale :

DECISION_PATH           -- Chemin emprunté (1, 2 ou 3)
RECO_TYPE               -- Type reco courte
RECO_SELECTIONNEE       -- Recommandation explicite
CAPPING_APPLIED         -- Type de capping appliqué

PRIX_RECOMMANDE         -- Prix final PT2QE
PCT_HAUSSE_FINALE       -- % de hausse (0.0523 = 5,23%)

Utilisation : - Base pour toutes les analyses pivots - Investigation ligne à ligne - Validation qualité - Export vers Excel pour présentations

Export 2 : statistics_by_dimension.csv

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

Structure :

DIMENSION               -- TYPE_CLIENT / TYPE_RESTAURANT / UNIVERS
VALEUR                  -- Valeur spécifique (ex: RCI PI GI)
NB_OFFRES               -- Nombre d'offres
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 (%)
PCT_HAUSSE_MIN          -- Hausse minimale (%)
PCT_HAUSSE_MAX          -- Hausse maximale (%)
PCT_HAUSSE_STDDEV       -- Écart-type des hausses (%)

Utilisation : - Comparaison inter-segments - Identification des segments les plus impactés - Détection d'anomalies (hausse moyenne anormale) - Support aux décisions de calibrage

Export 3 : impact_analysis.csv

Objectif : Impact CA et distribution des hausses par segment

Agrégation : TYPE_CLIENT × UNIVERS

Colonnes :

Volumétrie :

TYPE_CLIENT, UNIVERS
NB_OFFRES               -- Nombre d'offres du segment

Impact CA :

CA_ACTUEL               -- Somme des prix actuels (approx CA)
CA_FUTUR                -- Somme des prix recommandés
IMPACT_EUROS            -- Gain CA en € (CA_FUTUR - CA_ACTUEL)
IMPACT_PCT              -- Gain CA en % ((CA_FUTUR/CA_ACTUEL - 1) × 100)
HAUSSE_MOY_PCT          -- Hausse moyenne pondérée

Distribution des hausses (comptage absolu) :

NB_SANS_HAUSSE          -- 0%
NB_0_2PCT               -- ]0%, 2%]
NB_2_5PCT               -- ]2%, 5%]
NB_5_10PCT              -- ]5%, 10%]
NB_10_15PCT             -- ]10%, 15%]
NB_15_20PCT             -- ]15%, 20%]
NB_PLUS_20PCT           -- > 20%

Distribution des hausses (pourcentages) :

PCT_SANS_HAUSSE         -- % d'offres à 0%
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%

Utilisation : - Estimation du gain CA potentiel par segment - Identification des segments à fort impact - Communication business aux décideurs - Priorisation pour déploiement progressif

Export 4 : price_increase_distribution.csv

Objectif : Histogramme global des hausses

Tranches détaillées (10 buckets) :

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%

Métriques par tranche :

TRANCHE_HAUSSE          -- Libellé de la tranche
NB_OFFRES               -- Volume d'offres
NB_CLIENTS_UNIQUES      -- Nombre de clients touchés
NB_ARTICLES_UNIQUES     -- Nombre d'articles touchés
PRIX_MOY_ACTUEL         -- Prix moyen actuel dans la tranche
PRIX_MOY_RECOMMANDE     -- Prix moyen recommandé
HAUSSE_MIN_PCT          -- Hausse min dans la tranche
HAUSSE_MAX_PCT          -- Hausse max dans la tranche
HAUSSE_MOY_PCT          -- Hausse moyenne de la tranche
PCT_OFFRES              -- % d'offres dans cette tranche
PCT_CUMULE              -- % cumulé jusqu'à cette tranche

Utilisation : - Vision synthétique de l'agressivité globale - Identification rapide des outliers - Communication visuelle (histogramme) - Benchmark entre simulations - Validation des paramètres de capping

Lecture rapide :

Profil CONSERVATEUR :

80%+ des offres entre 0-10%
PCT_CUMULE atteint 90% à la tranche 7-10%
Peu d'offres > 15%

Profil AGRESSIF :

50%+ des offres entre 10-20%
PCT_CUMULE atteint 90% à la tranche 15-17%
Hausses bien réparties

Profil PROBLÉMATIQUE :

20%+ des offres > 20%
Investigation urgente nécessaire
Revoir les cappings

Export 5 : decision_path_analysis.csv

Objectif : Statistiques par chemin de décision et type de recommandation

Agrégation : DECISION_PATH × RECO_SELECTIONNEE

Colonnes :

Dimensions de l'arbre :

DECISION_PATH           -- PAS_BAISSE_GEL_PRIX / PL1_CONSERVATION_PREMIUM / OPTIMISATION_STANDARD
RECO_SELECTIONNEE       -- GEL_PRIX / CONSERVATION_PREMIUM / RECO1_* / RECO2_*

Volumétrie :

NB_OFFRES               -- Nombre d'offres par combinaison
NB_CLIENTS              -- Clients uniques
NB_ARTICLES             -- Articles uniques

Statistiques de hausse :

HAUSSE_MOY_PCT          -- Hausse moyenne (%)
HAUSSE_MEDIANE_PCT      -- Hausse médiane (%)

Distribution des cappings :

NB_CAP_GEL              -- Nombre avec CAPPING_APPLIED = GEL_PAS
NB_CAP_PRB              -- Nombre avec PRB_FINAL
NB_CAP_PLANCHER         -- Nombre avec PLANCHER_PL2_PL3
NB_CAP_BASIQUES         -- Nombre avec BASIQUES_50PCT
NB_CAP_SENSIBILITE      -- Nombre avec SENSIBILITE
NB_SANS_CAPPING         -- Nombre sans capping

Utilisation : - Comprendre la répartition entre les 3 chemins - Identifier quel chemin génère le plus de hausses - Analyser l'impact de chaque type de capping - Calibrer les seuils de déclenchement

Exemple d'analyse :

DECISION_PATH: OPTIMISATION_STANDARD
RECO_SELECTIONNEE: RECO1_REPOSITIONNEMENT_PALIERS
NB_OFFRES: 45000
HAUSSE_MOY_PCT: 6,2%
NB_CAP_SENSIBILITE: 12000
NB_CAP_BASIQUES: 3000
NB_SANS_CAPPING: 30000

→ Interprétation :
  - 67% des offres en OPTIMISATION_STANDARD
  - RECO1 gagne dans la majorité des cas
  - Capping sensibilité actif pour 27% des offres
  - Capping basiques actif pour 7%
  - 67% sans capping = paliers bien calibrés

Export 6 : capping_distribution.csv

Objectif : Distribution détaillée des cappings appliqués

Agrégation : CAPPING_APPLIED × DECISION_PATH × RECO_SELECTIONNEE

Colonnes :

CAPPING_APPLIED         -- Type de capping (GEL_PAS, PRB_FINAL, etc.)
DECISION_PATH           -- Chemin emprunté
RECO_SELECTIONNEE       -- Recommandation finale
NB_OFFRES               -- Volume d'offres
HAUSSE_MOY_PCT          -- Hausse moyenne dans cette combinaison

Types de capping analysés :

GEL_PAS                 -- Gel total (CHEMIN 1)
PRB_FINAL               -- Plafond absolu PRB
PLANCHER_PL2_PL3        -- Plancher de sécurité (CHEMIN 2)
BASIQUES_50PCT          -- Capping produits basiques
SENSIBILITE             -- Capping selon sensibilité prix
NONE                    -- Aucun capping

Utilisation : - Mesurer l'impact de chaque type de capping - Identifier les cappings les plus contraignants - Calibrer les paramètres (ex: 50% pour basiques est-il adapté ?) - Comprendre les interactions entre chemins et cappings

Exemple d'analyse :

CAPPING_APPLIED: BASIQUES_50PCT
DECISION_PATH: OPTIMISATION_STANDARD
RECO_SELECTIONNEE: RECO1_REPOSITIONNEMENT_PALIERS
NB_OFFRES: 5000
HAUSSE_MOY_PCT: 35%

→ Interprétation :
  - Capping basiques actif sur 5000 offres
  - Hausse moyenne de 35% (proche du plafond 50%)
  - Preuve que sans ce capping, hausses auraient été > 50%
  - Le capping basiques est effectif et utile

Export 7 : capping_cubes_generated.csv

Objectif : Cappings générés par cube pour ajustement éventuel

Structure :

UNIVERS                 -- ZOOM1
TYPE_CLIENT             -- Segment client
TYPE_RESTAURANT         -- Type établissement
GEO                     -- Zone géographique
CUBE_TYPE               -- MASTER ou NATIONAL
CAPPING_HIGH            -- Taux HIGH (ex: 0,025)
CAPPING_MEDIUM          -- Taux MEDIUM (ex: 0,05)
CAPPING_LOW             -- Taux LOW (ex: 0,075)

Utilisation : - Base pour créer capping_cubes_corrections.csv - Voir les valeurs appliquées par cube - Identifier les cubes à ajuster


Configuration avancée

Fichier pt2qe_config.json

Emplacement : config/pt2qe_config.json

Chargement : Automatique au démarrage de PT2QE

Structure complète :

{
  "processing": {
    "batch_size": 100000,
    "parallel_degree": 8
  },
  "capping": {
    "default_high": 0.05,
    "default_medium": 0.15,
    "default_low": 0.20,
    "basiques": 0.50,
    "allow_overrides": true
  },
  "recommendations": {
    "reco1_rules": [
      {
        "position": "ABOVE_PL1",
        "condition": "PRIX_TARIF_ACTUEL > NEW_BORNE_PL1_PL2",
        "action": "NO_CHANGE",
        "target": "PRIX_TARIF_ACTUEL",
        "comment": "Prix déjà en PL1, pas de changement"
      },
      ...
    ],
    "selection_rule": "max"
  },
  "output": {
    "csv_separator": ";",
    "csv_encoding": "cp1252",
    "decimal_places": 3,
    "percentage_format": 2
  }
}

Section processing

Paramètres de traitement Oracle :

"processing": {
  "batch_size": 100000,      // Taille des batchs SQL
  "parallel_degree": 8        // Degré de parallélisation Oracle
}

Utilisation : - Optimisation des requêtes volumineuses - Ajuster selon les ressources serveur

Section capping

Cappings par défaut :

"capping": {
  "default_high": 0.05,       // 5% si HIGH et pas de valeur fichier CSV
  "default_medium": 0.15,     // 15% si MEDIUM
  "default_low": 0.20,        // 20% si LOW
  "basiques": 0.50,           // 50% pour produits basiques
  "allow_overrides": true     // Autoriser les corrections
}

Modification :

Pour changer les valeurs par défaut : 1. Éditer config/pt2qe_config.json 2. Modifier les taux souhaités 3. Relancer PT2QE

⚠️ Attention : Les valeurs du fichier CSV capping_type_client.csv prioritaires sur les valeurs du JSON.

Section recommendations

Règles de repositionnement RECO1 :

Voir section "Recommandation 1 : Repositionnement par paliers" pour la documentation complète.

Règle de sélection :

"selection_rule": "max"     // MAX(RECO1, RECO2) - actuellement seule règle supportée

Section output

Formats d'export :

"output": {
  "csv_separator": ";",       // Séparateur CSV
  "csv_encoding": "cp1252",   // Encodage Windows
  "decimal_places": 3,        // Décimales pour les prix
  "percentage_format": 2      // Décimales pour les %
}

Modification :

Pour changer le format d'export : 1. Éditer config/pt2qe_config.json 2. Modifier les valeurs souhaitées 3. Relancer PT2QE

Exemples :

// Format européen (défaut)
{
  "csv_separator": ";",
  "decimal_places": 3
}

// Format US
{
  "csv_separator": ",",
  "decimal_places": 2
}

Points d'attention et limites

Périmètre fonctionnel

Restrictions : - ZOOM1 EXCLUSIF : Les offres ZOOM2/ZOOM3 sont exclues - Offres valides : Uniquement DT_FIN > SYSDATE - Conditions actives : FG_CND_VLD = 'X' - Types de conditions : ZFAP, ZFSP, ZIAP, ZISP - Séquences : A305 et A565 uniquement

Exclusions produits : - ID_GMM = 'PSN' - LC_HIC_SYSCO_N2 IN ('Divers', 'Freezer') - LC_HI1 = 'Qualificatif article inconnu'

Exclusions clients : - ID_TC_CG = 'AUTRES'

Dépendances externes

Prérequis obligatoires :

  1. Tables PT1CE :
  2. PT1CE_OPTIMAL_ZOOM1
  3. PT1CE_OPTIMAL_ZOOM2
  4. PT1CE_OPTIMAL_ZOOM3
  5. Doivent contenir des corridors avec STATUS = 'OPTIMAL'

  6. Tables de mapping :

  7. PT0CE_TYPE_CLIENT_MAPPING
  8. PT0CE_TYPE_RESTAURANT_MAPPING
  9. Doivent couvrir les combinaisons ZOOM1

  10. Calendrier fiscal :

  11. SYS_MD_CALENDRIER_SYSCO
  12. Doit contenir les 4 derniers trimestres complets

Vérification : Utiliser PT2QE_Menu.bat → Option 5

Cas particuliers

Nouveaux clients

Situation : Client sans historique transactionnel

Comportement : - FG_HM = NULL → Pas de calcul UNIVERS - Pas de matching TYPE_CLIENT → Exclu

Solution : Attendre que le client génère des transactions

Articles saisonniers

Situation : Article avec peu de transactions sur 4Q

Comportement : - MT_CAB_4Q faible - Historique incomplet mais traité

Impact : Recommandations potentiellement moins fiables

Corridors manquants

Situation : Pas de corridor MASTER ni NATIONAL pour un article

Comportement : - MATCH_TYPE = NO_MATCH - HAS_CORRIDOR = 0 - Offre exclue du calcul de recommandations

Solution : Exécuter PT1CE pour générer les corridors manquants

Cohérence tarifaire

Garanties PT2QE :

  1. Cohérence verticale :
  2. PRIX_RECOMMANDE >= NEW_PAS (toujours)
  3. PRIX_RECOMMANDE <= NEW_PRB (si capping PRB actif)

  4. Cohérence horizontale :

  5. Hausses alignées sur l'évolution des coûts (RECO2)
  6. Repositionnement vers paliers supérieurs (RECO1)

  7. Cohérence commerciale :

  8. Respect des cappings par sensibilité
  9. Protection des produits basiques
  10. Conservation des clients premium (CHEMIN 2)

Non garanti : - Cohérence inter-clients (même article peut avoir des hausses différentes) - Cohérence temporelle (run suivant peut recommander des prix différents si corridor change)

Limitations techniques

Volume maximal : - Dépend des ressources Oracle - Testé sur ~500k offres - Au-delà : risque de timeout

Temps d'exécution : - Variable selon le volume - Dépend du degré de parallélisation - Dépend de la charge serveur

Espace disque : - Tables temporaires volumineuses - CSV d'export peuvent être lourds - Prévoir espace suffisant dans outputs/

Mémoire : - Python pandas peut nécessiter de la RAM pour les gros fichiers CSV - Recommandation : 8 GB RAM minimum