Système de capping PT2QE¶
Définition du capping¶
Le capping est un mécanisme de limitation de la hausse de prix appliqué sur RECO1 (recommandation par repositionnement de paliers). Il n'affecte pas RECO2 (hausse proportionnelle au PAS).
Principe : Si RECO1 propose une hausse trop agressive, le capping ramène le prix à un niveau acceptable en fonction de la sensibilité prix du produit.
Formule de base :
PRIX_MAX_AVEC_CAPPING = PRIX_ACTUEL × (1 + TAUX_CAPPING)
RECO1_CAPPEE = MIN(RECO1_BASE, PRIX_MAX_AVEC_CAPPING)
Cascade de capping : étapes de calcul¶
PT2QE applique 4 étapes successives de capping avant d'obtenir le prix final recommandé :
Étape 1 : RECO1_BASE (calcul brut)¶
Algorithme : Repositionnement par paliers selon règles configurées dans pt2qe_config.json.
Règles par défaut : - Prix en PL1 → conservation (pas de changement) - Prix en PL1_PL2 ou PL2_PL3 → remonter vers PL1 - Prix en PL3_PL4 → remonter vers PL2 - Prix en PL4_PL5 → remonter vers PL3 - Prix en PL5_PL6 → remonter vers PL5 - Prix en PL6_PLX → remonter vers PL6 - Prix < PAS → remonter au PAS
Colonne SQL : RECO1_BASE
Exemple : - Prix actuel = 10,00€ (position PL3_PL4) - Borne PL2_PL3 = 12,00€ - RECO1_BASE = 12,00€ (hausse brute de 20%)
Étape 2 : RECO1_APRES_CAPPING_SENSIBILITE¶
Algorithme : Application du capping selon la sensibilité prix (HIGH/MEDIUM/LOW).
Logique SQL :
CASE
WHEN PRICE_SENSITIVITY = 'HIGH' THEN
LEAST(RECO1_BASE, PRIX_ACTUEL × (1 + CAPPING_HIGH))
WHEN PRICE_SENSITIVITY = 'MEDIUM' THEN
LEAST(RECO1_BASE, PRIX_ACTUEL × (1 + CAPPING_MEDIUM))
WHEN PRICE_SENSITIVITY = 'LOW' THEN
LEAST(RECO1_BASE, PRIX_ACTUEL × (1 + CAPPING_LOW))
ELSE RECO1_BASE
END
Colonne SQL : RECO1_APRES_CAPPING_SENSIBILITE
Exemple : - RECO1_BASE = 12,00€ - Prix actuel = 10,00€ - Sensibilité = HIGH - CAPPING_HIGH = 0,05 (5%) - Prix max autorisé = 10,00€ × 1,05 = 10,50€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(12,00€, 10,50€) = 10,50€
Étape 3 : RECO1_AVEC_CAPPING (cascade basiques)¶
Algorithme : Application du capping produits basiques (50% max) si LC_ATTRIBUT = 'Basiques'.
Logique SQL :
CASE
WHEN LC_ATTRIBUT = 'Basiques' THEN
LEAST(RECO1_APRES_CAPPING_SENSIBILITE, PRIX_ACTUEL × 1.50)
ELSE RECO1_APRES_CAPPING_SENSIBILITE
END
Colonne SQL : RECO1_AVEC_CAPPING
Exemple A (produit basique avec capping basiques actif) : - RECO1_APRES_CAPPING_SENSIBILITE = 10,50€ - Prix actuel = 10,00€ - LC_ATTRIBUT = 'Basiques' - Prix max basiques = 10,00€ × 1,50 = 15,00€ - RECO1_AVEC_CAPPING = MIN(10,50€, 15,00€) = 10,50€ (capping sensibilité plus restrictif)
Exemple B (produit basique avec capping basiques plus restrictif) : - RECO1_APRES_CAPPING_SENSIBILITE = 17,00€ (sensibilité LOW, capping à 20%) - Prix actuel = 14,00€ - LC_ATTRIBUT = 'Basiques' - Prix max basiques = 14,00€ × 1,50 = 21,00€ - Mais avec sensibilité LOW (20%) : 14,00€ × 1,20 = 16,80€ - RECO1_APRES_CAPPING_SENSIBILITE = 16,80€ - RECO1_AVEC_CAPPING = MIN(16,80€, 21,00€) = 16,80€
Exemple C (produit basique où le capping basiques devient déterminant) : - Prix actuel = 8,00€ - RECO1_BASE = 14,00€ (hausse brute de 75%) - Sensibilité = LOW, CAPPING_LOW = 0,20 (20%) - Prix max sensibilité = 8,00€ × 1,20 = 9,60€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(14,00€, 9,60€) = 9,60€ - LC_ATTRIBUT = 'Basiques' - Prix max basiques = 8,00€ × 1,50 = 12,00€ - RECO1_AVEC_CAPPING = MIN(9,60€, 12,00€) = 9,60€ (capping sensibilité toujours le plus restrictif)
Note importante : Le capping basiques intervient après le capping sensibilité. Il ne s'applique que si plus restrictif que le capping sensibilité déjà appliqué.
Étape 4 : PRIX_RECOMMANDE (arbre de décision + capping PRB final)¶
Algorithme : Sélection selon DECISION_PATH (3 chemins) + application capping PRB final.
Logique SQL :
PRIX_AVANT_CAPPING_PRB = CASE
-- CHEMIN 1 : Gel prix (PAS en baisse)
WHEN NEW_PAS < PAS_ACTIF THEN PRIX_ACTUEL
-- CHEMIN 2 : Conservation premium (prix en PL1 anciennes bornes)
WHEN PRIX_ACTUEL > BORNE_PL1_PL2 AND PRIX_ACTUEL <= PRB_ACTIF THEN
GREATEST(PRIX_ACTUEL, NEW_BORNE_PL2_PL3) -- Plancher PL2_PL3
-- CHEMIN 3 : Optimisation standard
ELSE GREATEST(RECO1_AVEC_CAPPING, RECO2)
END
PRIX_RECOMMANDE = LEAST(PRIX_AVANT_CAPPING_PRB, NEW_PRB)
Colonne SQL : PRIX_RECOMMANDE
Exemple CHEMIN 3 : - RECO1_AVEC_CAPPING = 10,50€ - RECO2 = 10,30€ - PRIX_AVANT_CAPPING_PRB = MAX(10,50€, 10,30€) = 10,50€ - NEW_PRB = 11,00€ - PRIX_RECOMMANDE = MIN(10,50€, 11,00€) = 10,50€
Arbre de décision : 3 chemins¶
CHEMIN 1 : PAS_BAISSE_GEL_PRIX¶
Condition de déclenchement :
Action : - Prix recommandé = Prix actuel (gel total) - Aucune hausse appliquée (0%) - Aucun capping n'entre en jeu
Rationale : Ne pas répercuter les baisses de coût d'achat au client.
Colonnes SQL :
- DECISION_PATH = 'PAS_BAISSE_GEL_PRIX'
- RECO_SELECTIONNEE = 'GEL_PRIX'
- CAPPING_APPLIED = 'GEL_PAS'
- PCT_HAUSSE_FINALE = 0
Exemple : - PAS actuel = 8,50€ - Nouveau PAS = 8,00€ (baisse de 0,50€) - Prix actuel = 10,00€ - Prix recommandé = 10,00€ (gel) - Hausse = 0%
CHEMIN 2 : PL1_CONSERVATION_PREMIUM¶
Condition de déclenchement :
Le prix actuel est dans PL1 des anciennes bornes (référence PT0CE).
Action : 1. Conservation du prix actuel 2. Application d'un plancher de sécurité = NEW_BORNE_PL2_PL3 3. Application du capping PRB final
Logique SQL :
Rationale : Maintenir les clients premium en position haute tout en évitant la compression du corridor (si PL2_PL3 remonte, on suit).
Colonnes SQL :
- DECISION_PATH = 'PL1_CONSERVATION_PREMIUM'
- RECO_SELECTIONNEE = 'CONSERVATION_PREMIUM'
- CAPPING_APPLIED = 'PLANCHER_PL2_PL3' (si plancher actif) ou 'PRB_FINAL' (si PRB actif) ou 'NONE'
Exemple A (plancher inactif) : - Prix actuel = 15,00€ - BORNE_PL1_PL2 (anciennes) = 14,00€ - PRB_ACTIF = 16,00€ - → Prix en PL1 anciennes ✓ - NEW_BORNE_PL2_PL3 = 13,00€ - NEW_PRB = 17,00€ - Prix recommandé = LEAST(MAX(15,00€, 13,00€), 17,00€) = 15,00€ - Hausse = 0% - CAPPING_APPLIED = 'NONE'
Exemple B (plancher actif) : - Prix actuel = 13,00€ - BORNE_PL1_PL2 (anciennes) = 12,00€ - PRB_ACTIF = 16,00€ - → Prix en PL1 anciennes ✓ - NEW_BORNE_PL2_PL3 = 13,50€ (remonte) - NEW_PRB = 17,00€ - Prix recommandé = LEAST(MAX(13,00€, 13,50€), 17,00€) = 13,50€ - Hausse = 3,8% - CAPPING_APPLIED = 'PLANCHER_PL2_PL3'
Exemple C (PRB actif) : - Prix actuel = 15,50€ - BORNE_PL1_PL2 (anciennes) = 14,00€ - PRB_ACTIF = 16,00€ - → Prix en PL1 anciennes ✓ - NEW_BORNE_PL2_PL3 = 13,00€ - NEW_PRB = 15,00€ (compression du corridor) - Prix recommandé = LEAST(MAX(15,50€, 13,00€), 15,00€) = 15,00€ - Hausse = -3,2% (baisse imposée par PRB) - CAPPING_APPLIED = 'PRB_FINAL'
CHEMIN 3 : OPTIMISATION_STANDARD¶
Condition de déclenchement :
Action : 1. Calcul RECO1 avec cascade de cappings (sensibilité → basiques) 2. Calcul RECO2 (hausse proportionnelle PAS) 3. Sélection = MAX(RECO1_cappée, RECO2) 4. Application capping PRB final
Logique SQL :
Rationale : Optimisation classique avec double recommandation + protection corridor.
Colonnes SQL :
- DECISION_PATH = 'OPTIMISATION_STANDARD'
- RECO_SELECTIONNEE = 'RECO1_REPOSITIONNEMENT_PALIERS' ou 'RECO2_HAUSSE_PROPORTIONNELLE_PAS'
- CAPPING_APPLIED = 'SENSIBILITE' ou 'BASIQUES_50PCT' ou 'PRB_FINAL' ou 'NONE'
Exemple A (RECO1 gagne, capping sensibilité actif) : - Prix actuel = 10,00€ - RECO1_BASE = 12,00€ - Sensibilité = HIGH, CAPPING_HIGH = 0,05 - RECO1_AVEC_CAPPING = MIN(12,00€, 10,50€) = 10,50€ - RECO2 = 10,30€ - Prix avant PRB = MAX(10,50€, 10,30€) = 10,50€ - NEW_PRB = 11,00€ - Prix recommandé = MIN(10,50€, 11,00€) = 10,50€ - Hausse = 5% - RECO_SELECTIONNEE = 'RECO1_REPOSITIONNEMENT_PALIERS' - CAPPING_APPLIED = 'SENSIBILITE'
Exemple B (RECO2 gagne, pas de capping) : - Prix actuel = 10,00€ - RECO1_BASE = 10,20€ - Sensibilité = HIGH, CAPPING_HIGH = 0,05 - RECO1_AVEC_CAPPING = MIN(10,20€, 10,50€) = 10,20€ - RECO2 = 10,80€ (hausse PAS de 8%) - Prix avant PRB = MAX(10,20€, 10,80€) = 10,80€ - NEW_PRB = 11,00€ - Prix recommandé = MIN(10,80€, 11,00€) = 10,80€ - Hausse = 8% - RECO_SELECTIONNEE = 'RECO2_HAUSSE_PROPORTIONNELLE_PAS' - CAPPING_APPLIED = 'NONE' (RECO2 n'est jamais cappée)
Exemple C (capping basiques actif) : - Prix actuel = 8,00€ - LC_ATTRIBUT = 'Basiques' - RECO1_BASE = 14,00€ - Sensibilité = LOW, CAPPING_LOW = 0,20 - RECO1_APRES_CAPPING_SENSIBILITE = MIN(14,00€, 9,60€) = 9,60€ - RECO1_AVEC_CAPPING = MIN(9,60€, 12,00€) = 9,60€ - RECO2 = 8,50€ - Prix avant PRB = MAX(9,60€, 8,50€) = 9,60€ - NEW_PRB = 11,00€ - Prix recommandé = MIN(9,60€, 11,00€) = 9,60€ - Hausse = 20% - RECO_SELECTIONNEE = 'RECO1_REPOSITIONNEMENT_PALIERS' - CAPPING_APPLIED = 'SENSIBILITE' (le capping sensibilité était le plus restrictif, même si on a vérifié basiques)
Exemple D (capping PRB actif) : - Prix actuel = 10,00€ - RECO1_AVEC_CAPPING = 11,50€ - RECO2 = 10,80€ - Prix avant PRB = MAX(11,50€, 10,80€) = 11,50€ - NEW_PRB = 11,00€ (corridor compressé) - Prix recommandé = MIN(11,50€, 11,00€) = 11,00€ - Hausse = 10% - RECO_SELECTIONNEE = 'RECO1_REPOSITIONNEMENT_PALIERS' - CAPPING_APPLIED = 'PRB_FINAL'
Ordre de priorité des cappings appliqués¶
La colonne CAPPING_APPLIED indique le capping le plus contraignant qui a limité le prix final. Ordre de priorité (du plus prioritaire au moins prioritaire) :
- GEL_PAS : Gel total du prix (CHEMIN 1)
- Condition : NEW_PAS < PAS_ACTIF
-
Hausse = 0%
-
PRB_FINAL : Plafond absolu PRB
- Condition : Prix avant capping PRB > NEW_PRB
-
S'applique sur tous les chemins
-
PLANCHER_PL2_PL3 : Plancher de sécurité (CHEMIN 2)
- Condition : Prix actuel < NEW_BORNE_PL2_PL3 dans CHEMIN 2
-
Hausse forcée pour maintenir position
-
BASIQUES_50PCT : Capping produits basiques
- Condition : LC_ATTRIBUT = 'Basiques' ET RECO1_après_sensibilité > Prix × 1,50
-
S'applique uniquement si plus restrictif que le capping sensibilité
-
SENSIBILITE : Capping selon sensibilité prix
- Condition : RECO1_BASE > Prix × (1 + capping_sensibilité)
-
Premier niveau de protection
-
NONE : Aucun capping appliqué
- RECO1 ou RECO2 sans limitation
Règle de détermination :
CASE
WHEN DECISION_PATH = 'PAS_BAISSE_GEL_PRIX' THEN 'GEL_PAS'
WHEN PRIX_AVANT_CAPPING_PRB > NEW_PRB THEN 'PRB_FINAL'
WHEN DECISION_PATH = 'PL1_CONSERVATION_PREMIUM'
AND PRIX_ACTUEL < NEW_BORNE_PL2_PL3 THEN 'PLANCHER_PL2_PL3'
WHEN DECISION_PATH = 'OPTIMISATION_STANDARD'
AND LC_ATTRIBUT = 'Basiques'
AND RECO1_APRES_CAPPING_SENSIBILITE > PRIX_ACTUEL × 1.50 THEN 'BASIQUES_50PCT'
WHEN DECISION_PATH = 'OPTIMISATION_STANDARD'
AND RECO1_BASE > RECO1_APRES_CAPPING_SENSIBILITE THEN 'SENSIBILITE'
ELSE 'NONE'
END
Configuration des cappings : 3 niveaux hiérarchiques¶
Niveau 1 : Configuration globale (par défaut)¶
Fichier : config/pt2qe_config.json
Utilisation : Valeurs par défaut si aucun capping spécifique n'est défini.
Structure JSON :
{
"capping": {
"default_high": 0.05,
"default_medium": 0.15,
"default_low": 0.20,
"basiques": 0.50,
"allow_overrides": true
}
}
Paramètres :
- default_high : Capping pour sensibilité HIGH (défaut : 5%)
- default_medium : Capping pour sensibilité MEDIUM (défaut : 15%)
- default_low : Capping pour sensibilité LOW (défaut : 20%)
- basiques : Capping produits basiques (défaut : 50%)
- allow_overrides : Autoriser les surcharges (défaut : true)
Modification :
1. Éditer config/pt2qe_config.json
2. Modifier les valeurs numériques (format décimal : 0.05 = 5%)
3. Sauvegarder
4. Relancer le traitement complet (option 1)
Note : Ces valeurs sont utilisées uniquement si aucun capping spécifique n'est trouvé aux niveaux 2 et 3.
Niveau 2 : Cappings par type client¶
Fichier : inputs/capping_type_client.csv
Utilisation : Cappings appliqués par TYPE_CLIENT. Obligatoire pour l'option 1.
Format CSV : - Encodage : CP1252 - Séparateur : point-virgule (;) - Décimale : virgule (,) - En-têtes obligatoires
Structure :
TYPE_CLIENT;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
RCI PI GI;0,025;0,05;0,075
RSI HM;0,025;0,05;0,075
RSC HM;0,025;0,05;0,075
RSC HM - SRCNAT;0,025;0,05;0,075
RSI HM - SRCREG;0,025;0,05;0,075
RCI autres;0,025;0,05;0,075
NATIONAL;0,025;0,05;0,075
Colonnes :
- TYPE_CLIENT (texte) : Identifiant du type client (doit exister dans PT0CE_TYPE_CLIENT_MAPPING)
- CAPPING_HIGH (numérique) : Capping pour sensibilité HIGH
- CAPPING_MEDIUM (numérique) : Capping pour sensibilité MEDIUM
- CAPPING_LOW (numérique) : Capping pour sensibilité LOW
Règles de validation : 1. TYPE_CLIENT doit correspondre à une valeur existante dans les mappings 2. Valeurs de capping entre 0 et 1 (0,05 = 5%, 1 = 100%) 3. Cohérence : CAPPING_HIGH ≤ CAPPING_MEDIUM ≤ CAPPING_LOW 4. Au moins une ligne doit être présente 5. Ligne 'NATIONAL' recommandée comme fallback
Création du fichier :
- Copier le template ci-dessus dans un nouveau fichier
- Éditer les valeurs de capping selon la stratégie tarifaire
- Sauvegarder sous
inputs/capping_type_client.csv - Vérifier l'encodage (CP1252) et les séparateurs
Exemple d'ajustement :
Pour augmenter l'agressivité sur RCI PI GI :
(au lieu de 0,025 / 0,05 / 0,075)Pour être plus conservateur sur RSI HM :
Modification :
1. Ouvrir inputs/capping_type_client.csv dans Excel ou éditeur texte
2. Modifier les valeurs de capping (virgule comme séparateur décimal)
3. Sauvegarder sans changer l'encodage
4. Relancer le traitement complet (option 1 du menu)
Erreurs courantes : - Encodage incorrect → Caractères spéciaux non reconnus - Séparateur incorrect (virgule au lieu de point-virgule) → Parsing échoué - Décimale incorrecte (point au lieu de virgule) → Valeurs erronées - TYPE_CLIENT inexistant → Capping ignoré
Niveau 3 : Cappings par cube (corrections)¶
Fichier : corrections/capping_cubes_corrections.csv
Utilisation : Cappings spécifiques pour des combinaisons UNIVERS × TYPE_CLIENT × TYPE_RESTAURANT × GEO. Optionnel, utilisé avec l'option 2.
Format CSV : - Encodage : CP1252 - Séparateur : point-virgule (;) - Décimale : virgule (,) - En-têtes obligatoires
Structure :
UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;REST. TRADI;IDF;0,03;0,07;0,10
ZOOM1;RCI PI GI;REST. TRADI;NO;0,025;0,05;0,08
ZOOM1;RSI HM;SOCIAL;NO;0,02;0,06;0,09
ZOOM1;RSI HM;RESTO ENTREPRISE;NO;0,02;0,06;0,09
Colonnes :
- UNIVERS (texte) : ZOOM1, ZOOM2 ou ZOOM3
- TYPE_CLIENT (texte) : Type client spécifique
- TYPE_RESTAURANT (texte) : Type restaurant spécifique
- GEO (texte) : Zone géographique (IDF, NO, etc.) ou NULL
- CAPPING_HIGH (numérique) : Capping pour sensibilité HIGH
- CAPPING_MEDIUM (numérique) : Capping pour sensibilité MEDIUM
- CAPPING_LOW (numérique) : Capping pour sensibilité LOW
Règles de validation : 1. Les 4 premières colonnes définissent la clé unique du cube 2. Au moins une valeur de capping (HIGH/MEDIUM/LOW) doit être renseignée 3. Les valeurs de capping écrasent celles du niveau 2 pour ce cube spécifique 4. GEO peut être NULL (s'applique à toutes les zones)
Création du fichier (méthode recommandée) :
-
Exécuter l'option 1 pour générer
capping_cubes_generated.csv -
Analyser les résultats :
- Ouvrir
outputs/run_*/capping_cubes_generated.csv -
Identifier les cubes nécessitant un ajustement
-
Copier le fichier généré :
-
Éditer les cappings :
- Ouvrir
corrections/capping_cubes_corrections.csv - Modifier uniquement les colonnes CAPPING_HIGH/MEDIUM/LOW
- Ne pas modifier les colonnes UNIVERS/TYPE_CLIENT/TYPE_RESTAURANT/GEO
-
Sauvegarder
-
Appliquer les corrections :
- Lancer l'option 2 du menu : "Ajuster les cappings"
Exemple de modification ciblée :
Problème identifié : RCI PI GI en Île-de-France avec trop de hausses > 10%
Solution :
UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;REST. TRADI;IDF;0,02;0,05;0,08
ZOOM1;RCI PI GI;RESTO LIVRAISON;IDF;0,02;0,05;0,08
ZOOM1;RCI PI GI;RESTO RAPIDE;IDF;0,025;0,06;0,09
Modification :
1. Ouvrir corrections/capping_cubes_corrections.csv
2. Modifier les valeurs de capping pour les cubes ciblés
3. Sauvegarder
4. Relancer l'option 2 du menu (ajustement cappings)
5. Analyser les nouveaux résultats
6. Si nécessaire, répéter le processus (itératif)
Tables Oracle générées¶
PT2QE_CAPPING_CUBES¶
Description : Table centrale contenant les cappings pour chaque cube de recommandation.
Création : Automatique lors de l'option 1, générée par CappingManager.generate_cube_capping_table().
Structure :
| Colonne | Type | Description |
|---|---|---|
| UNIVERS | VARCHAR2(20) | ZOOM1, ZOOM2 ou ZOOM3 |
| TYPE_CLIENT | VARCHAR2(100) | Type client (ou 'NATIONAL') |
| TYPE_RESTAURANT | VARCHAR2(100) | Type restaurant (ou 'NATIONAL') |
| GEO | VARCHAR2(100) | Zone géographique (ou 'NATIONAL') |
| CUBE_TYPE | VARCHAR2(20) | 'MASTER' ou 'NATIONAL' |
| CAPPING_HIGH | NUMBER | Capping sensibilité HIGH |
| CAPPING_MEDIUM | NUMBER | Capping sensibilité MEDIUM |
| CAPPING_LOW | NUMBER | Capping sensibilité LOW |
Types de cubes :
- MASTER : Cubes avec dimensions spécifiques
- Créés pour chaque combinaison unique trouvée dans les offres
-
Exemples : (ZOOM1, RCI PI GI, REST. TRADI, IDF), (ZOOM1, RSI HM, SOCIAL, NO)
-
NATIONAL : Cubes de fallback
- Créés automatiquement avec dimensions = 'NATIONAL'
- Utilisés si aucun cube MASTER ne correspond
- Cappings plus conservateurs par défaut
Population :
- Extraction des cubes distincts depuis
PT2QE_PRICE_OFFERS_ENRICHED - Création des cubes MASTER (MATCH_TYPE = 'MASTER')
- Création des cubes NATIONAL (MATCH_TYPE = 'NATIONAL')
- Application des cappings par type client (niveau 2)
- Application des corrections (niveau 3, si présentes)
Jointure avec les recommandations :
FROM PT2QE_PRICE_OFFERS_ENRICHED e
LEFT JOIN PT2QE_CAPPING_CUBES c
ON e.UNIVERS = c.UNIVERS
AND e.TYPE_CLIENT = c.TYPE_CLIENT
AND e.TYPE_RESTAURANT = c.TYPE_RESTAURANT
AND NVL(e.GEO, 'NULL') = NVL(c.GEO, 'NULL')
Requête de consultation :
-- Voir tous les cappings configurés
SELECT
UNIVERS,
TYPE_CLIENT,
TYPE_RESTAURANT,
GEO,
CUBE_TYPE,
CAPPING_HIGH,
CAPPING_MEDIUM,
CAPPING_LOW
FROM PT2QE_CAPPING_CUBES
ORDER BY UNIVERS, TYPE_CLIENT, TYPE_RESTAURANT, GEO;
-- Compter les cubes par type
SELECT
CUBE_TYPE,
COUNT(*) as NB_CUBES
FROM PT2QE_CAPPING_CUBES
GROUP BY CUBE_TYPE;
Processus d'ajustement des cappings : pas à pas¶
Flux de travail complet¶
[1. CALCUL INITIAL]
↓
[2. ANALYSE RÉSULTATS]
↓
Résultats OK ? ──OUI─→ [3. GÉNÉRATION FINALE]
↓ NON
[4. AJUSTEMENT CAPPINGS]
↓
[5. RECALCUL]
↓
[6. VALIDATION]
↓
Résultats OK ? ──OUI─→ [3. GÉNÉRATION FINALE]
↓ NON
[Retour étape 4]
Étape 1 : Calcul initial avec cappings par défaut¶
Action : Lancer l'option 1 du menu PT2QE.
Prérequis :
- Fichier inputs/capping_type_client.csv créé et rempli
- Tables PT1CE_OPTIMAL_* existantes (PT1CE doit avoir été exécuté)
Commande :
Processus exécuté : 1. Extraction des offres actuelles (ZOOM1 uniquement) avec historique 4Q 2. Enrichissement avec corridors PT1CE 3. Génération de PT2QE_CAPPING_CUBES avec cappings du niveau 2 4. Calcul des recommandations avec cascade de capping 5. Génération des analyses et exports
Durée : Variable selon le volume.
Sorties générées :
- outputs/run_YYYYMMDD_HHMMSS/recommendations_detail.csv
- outputs/run_YYYYMMDD_HHMMSS/impact_analysis.csv
- outputs/run_YYYYMMDD_HHMMSS/price_increase_distribution.csv
- outputs/run_YYYYMMDD_HHMMSS/decision_path_analysis.csv
- outputs/run_YYYYMMDD_HHMMSS/capping_distribution.csv
- outputs/run_YYYYMMDD_HHMMSS/capping_cubes_generated.csv ⭐
Vérification de succès : - Message "TRAITEMENT TERMINE AVEC SUCCES" - Fichiers CSV présents dans le dossier outputs/run_* - Nombre de recommandations > 0
Étape 2 : Analyse des résultats¶
Objectif : Identifier les cubes nécessitant un ajustement de capping.
Fichiers à analyser :
2.1. price_increase_distribution.csv¶
Contenu : Distribution des hausses par tranche.
Analyse : - Vérifier que la majorité des hausses sont dans les tranches souhaitées - Identifier les tranches sur-représentées
Exemple de lecture :
TRANCHE_HAUSSE;NB_OFFRES;PCT_OFFRES;PCT_CUMULE
00. Pas de hausse;1200;5,2;5,2
01. 0-2%;3500;15,1;20,3
02. 2-5%;8900;38,5;58,8
03. 5-7%;5600;24,2;83,0
04. 7-10%;2800;12,1;95,1
05. 10-12%;800;3,5;98,6
06. 12-15%;250;1,1;99,7
07. 15-20%;50;0,2;99,9
08. Plus de 20%;25;0,1;100,0
Interprétation : - 83% des offres ont une hausse ≤ 7% → Profil conservateur - 1,4% des offres ont une hausse > 10% → Acceptable - Si > 5% des offres ont une hausse > 15% → Ajustement nécessaire
2.2. decision_path_analysis.csv¶
Contenu : Statistiques par chemin de décision.
Analyse : - Vérifier la répartition entre les 3 chemins - Analyser les hausses moyennes par chemin - Identifier les cappings les plus actifs
Exemple de lecture :
DECISION_PATH;RECO_SELECTIONNEE;NB_OFFRES;HAUSSE_MOY_PCT;NB_CAP_SENSIBILITE;NB_CAP_BASIQUES
PAS_BAISSE_GEL_PRIX;GEL_PRIX;1200;0,0;0;0
PL1_CONSERVATION_PREMIUM;CONSERVATION_PREMIUM;3500;2,1;0;0
OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;15600;5,8;8900;1200
OPTIMISATION_STANDARD;RECO2_HAUSSE_PROPORTIONNELLE_PAS;2800;6,2;0;0
Interprétation : - OPTIMISATION_STANDARD = 80% des offres → Comportement normal - RECO1 gagne dans 85% des cas (15600/(15600+2800)) → Paliers bien calibrés - 8900 offres cappées par sensibilité → Capping actif et efficace - 1200 offres cappées par basiques → Capping basiques actif sur une minorité
2.3. capping_distribution.csv¶
Contenu : Détail des cappings appliqués.
Analyse : - Identifier les cappings les plus contraignants - Analyser la hausse moyenne par type de capping
Exemple de lecture :
CAPPING_APPLIED;DECISION_PATH;RECO_SELECTIONNEE;NB_OFFRES;HAUSSE_MOY_PCT
GEL_PAS;PAS_BAISSE_GEL_PRIX;GEL_PRIX;1200;0,0
PLANCHER_PL2_PL3;PL1_CONSERVATION_PREMIUM;CONSERVATION_PREMIUM;450;3,2
PRB_FINAL;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;2100;8,5
BASIQUES_50PCT;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;1200;18,2
SENSIBILITE;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;8900;4,8
NONE;OPTIMISATION_STANDARD;RECO1_REPOSITIONNEMENT_PALIERS;4500;6,1
NONE;OPTIMISATION_STANDARD;RECO2_HAUSSE_PROPORTIONNELLE_PAS;2800;6,2
Interprétation : - SENSIBILITE = capping le plus fréquent (8900 offres) - BASIQUES_50PCT = 1200 offres avec hausse moyenne de 18,2% → Attention : ce sont des produits basiques, le capping basiques limite à +50% mais la hausse moyenne réelle est de 18%, ce qui est cohérent - PRB_FINAL = 2100 offres plafonnées par le PRB → Corridors compressés - NONE = 7300 offres sans capping → 32% des offres en OPTIMISATION_STANDARD
2.4. impact_analysis.csv¶
Contenu : Impact CA par segment.
Analyse : - Identifier les segments avec impact CA anormal - Vérifier la cohérence des hausses moyennes
Exemple de lecture :
TYPE_CLIENT;UNIVERS;NB_OFFRES;CA_ACTUEL;CA_FUTUR;IMPACT_PCT;HAUSSE_MOY_PCT
RCI PI GI;ZOOM1;15600;1250000;1318750;5,5;5,5
RSI HM;ZOOM1;6500;520000;546000;5,0;5,0
RSC HM;ZOOM1;1100;88000;96800;10,0;10,0
Interprétation : - RCI PI GI : Impact CA +5,5% → Cohérent avec hausse moyenne 5,5% - RSC HM : Impact CA +10% → Plus agressif que les autres segments - Si RSC HM doit être plus conservateur → Ajustement nécessaire
Étape 3 : Décision d'ajustement¶
Critères de validation :
| Critère | Seuil acceptable | Action si dépassé |
|---|---|---|
| % offres avec hausse > 20% | < 2% | Réduire cappings LOW |
| % offres avec hausse > 15% | < 5% | Réduire cappings MEDIUM/LOW |
| Hausse moyenne globale | Selon objectif stratégique | Ajuster tous les cappings |
| Impact CA par segment | Selon contraintes business | Ajuster cappings spécifiques |
| % offres cappées par sensibilité | > 30% | Cappings bien calibrés |
| Hausse max observée | < 50% | Vérifier capping basiques |
Scénarios de décision :
Scénario A : Résultats conformes - Tous les critères respectés - → Passer directement à l'option 3 (Génération offres finales)
Scénario B : Ajustement global nécessaire
- Hausses trop agressives sur tous les segments
- → Modifier inputs/capping_type_client.csv
- → Relancer option 1 (calcul complet)
Scénario C : Ajustement ciblé nécessaire
- Hausses problématiques sur certains cubes spécifiques
- → Créer corrections/capping_cubes_corrections.csv
- → Lancer option 2 (ajustement cappings)
Étape 4 : Ajustement des cappings (si nécessaire)¶
4.1. Ajustement global (modifier niveau 2)¶
Quand : Problème généralisé sur un ou plusieurs TYPE_CLIENT.
Procédure :
-
Ouvrir le fichier de capping :
-
Modifier les valeurs :
Exemple : Réduire l'agressivité sur RSI HM
(au lieu de 0,025 / 0,05 / 0,075)-
Sauvegarder sans changer l'encodage (CP1252)
-
Relancer l'option 1 :
-
Analyser les nouveaux résultats
Note : Cette méthode recalcule tout depuis le début.
4.2. Ajustement ciblé (créer niveau 3)¶
Quand : Problème localisé sur des cubes spécifiques (ex: RCI PI GI en IDF).
Procédure :
-
Localiser le fichier de cappings générés :
-
Copier le fichier :
- Source :
outputs/run_YYYYMMDD_HHMMSS/capping_cubes_generated.csv -
Destination :
corrections/capping_cubes_corrections.csv -
Éditer le fichier de corrections :
a. Ouvrir corrections/capping_cubes_corrections.csv
b. Identifier les cubes à ajuster (selon l'analyse de l'étape 2)
c. Modifier uniquement les colonnes CAPPING_HIGH/MEDIUM/LOW
d. Ne pas modifier les colonnes de clé (UNIVERS, TYPE_CLIENT, TYPE_RESTAURANT, GEO)
Exemple :
UNIVERS;TYPE_CLIENT;TYPE_RESTAURANT;GEO;CAPPING_HIGH;CAPPING_MEDIUM;CAPPING_LOW
ZOOM1;RCI PI GI;REST. TRADI;IDF;0,020;0,045;0,070
ZOOM1;RCI PI GI;RESTO LIVRAISON;IDF;0,020;0,045;0,070
e. Sauvegarder
-
Lancer l'option 2 :
-
Vérifier le message de confirmation :
-
Analyser les nouveaux résultats dans
outputs/corrections_YYYYMMDD_HHMMSS/
Avantage : Recalcul rapide, ne recharge pas les données depuis Oracle.
Étape 5 : Validation des ajustements¶
Procédure :
- Ouvrir les nouveaux fichiers d'analyse :
- Si option 1 :
outputs/run_YYYYMMDD_HHMMSS/ -
Si option 2 :
outputs/corrections_YYYYMMDD_HHMMSS/ -
Comparer avec les résultats précédents :
a. Distribution des hausses :
b. Hausse moyenne par segment :
c. Impact CA global :
- Décider de la suite :
- Résultats OK → Passer à l'option 3
- Résultats insuffisants → Répéter l'étape 4 avec d'autres valeurs
- Résultats trop conservateurs → Augmenter les cappings
Limite d'itérations : Pas de limite technique, mais recommandé de ne pas dépasser 3-4 itérations pour éviter le sur-calibrage.
Étape 6 : Génération des offres finales¶
Quand : Après validation complète des résultats.
Procédure :
-
Lancer l'option 3 :
-
Confirmer l'action :
-
Vérifier la génération :
-
Consulter le fichier final :
Structure du fichier final :
ID_CLN;LC_CLN;ID_ART;LC_ART;TYPE_CLIENT;TYPE_RESTAURANT;GEO;UNIVERS;ID_CND;DT_DEB_CONDITION;DT_FIN_CONDITION;PRIX_TARIF_ACTUEL;NOUVEAU_PRIX;PCT_HAUSSE;HAUSSE_EUROS;POSITION_TARIF_ACTUEL_DANS_ANCIENNES_BORNES;PALIER_TARIF_ACTUEL_VS_NOUVELLES_BORNES;POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES;PRICE_SENSITIVITY;TYPE_HAUSSE;DATE_CALCUL
Colonnes clés :
- ID_CLN / ID_ART / ID_CND : Identifiants uniques
- PRIX_TARIF_ACTUEL : Prix actuel
- NOUVEAU_PRIX : Prix recommandé final
- PCT_HAUSSE : Pourcentage de hausse (en %)
- POSITION_NOUVEAU_PRIX_DANS_NOUVELLES_BORNES : Position finale dans le corridor
- TYPE_HAUSSE : REPOSITIONNEMENT ou HAUSSE_PROPORTIONNELLE
Validation finale : 1. Vérifier que le nombre d'offres correspond aux attentes 2. Contrôler les hausses minimales et maximales 3. Vérifier la cohérence des positions dans les corridors
Exemples pratiques détaillés¶
Exemple 1 : Cascade complète avec capping sensibilité¶
Contexte : - Client : ID_CLN = 123456 - Article : ID_ART = PROD789 - TYPE_CLIENT = RCI PI GI - TYPE_RESTAURANT = REST. TRADI - GEO = IDF - UNIVERS = ZOOM1 - LC_ATTRIBUT = Standard (pas de capping basiques)
Données initiales : - Prix actuel = 10,00€ - Position actuelle = PL3_PL4 (dans nouvelles bornes) - NEW_PAS = 6,50€ - NEW_PRB = 13,00€ - NEW_BORNE_PL2_PL3 = 11,50€ - PAS_ACTIF = 6,00€ - PRB_ACTIF = 12,50€ - PRICE_SENSITIVITY = HIGH - PAS en hausse : NEW_PAS > PAS_ACTIF ✓
Capping configuré : - CAPPING_HIGH = 0,05 (5%)
Calcul étape par étape :
1. RECO1_BASE (repositionnement brut) : - Position = PL3_PL4 - Règle = Remonter vers PL2 (borne PL2_PL3) - RECO1_BASE = 11,50€ - Hausse brute = (11,50 - 10,00) / 10,00 = +15%
2. RECO1_APRES_CAPPING_SENSIBILITE : - Sensibilité = HIGH - Capping = 5% - Prix max autorisé = 10,00€ × 1,05 = 10,50€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(11,50€, 10,50€) = 10,50€ - Hausse après capping = +5%
3. RECO1_AVEC_CAPPING (cascade basiques) : - LC_ATTRIBUT ≠ 'Basiques' - Pas de capping basiques à appliquer - RECO1_AVEC_CAPPING = 10,50€
4. RECO2 (hausse proportionnelle PAS) : - Hausse PAS = (6,50 - 6,00) / 6,00 = +8,33% - RECO2 = 10,00€ × 1,0833 = 10,83€
5. Arbre de décision : - NEW_PAS (6,50€) > PAS_ACTIF (6,00€) → Pas de gel - Prix actuel (10,00€) pas dans PL1 anciennes → Pas de conservation premium - → CHEMIN 3 : OPTIMISATION_STANDARD
6. Sélection finale : - MAX(RECO1_AVEC_CAPPING, RECO2) = MAX(10,50€, 10,83€) = 10,83€ - RECO_SELECTIONNEE = RECO2_HAUSSE_PROPORTIONNELLE_PAS
7. Capping PRB final : - Prix avant PRB = 10,83€ - NEW_PRB = 13,00€ - 10,83€ < 13,00€ → Pas de capping PRB - PRIX_RECOMMANDE = 10,83€
Résultat final : - Prix actuel : 10,00€ - Prix recommandé : 10,83€ - Hausse finale : +8,3% - DECISION_PATH = OPTIMISATION_STANDARD - RECO_SELECTIONNEE = RECO2_HAUSSE_PROPORTIONNELLE_PAS - CAPPING_APPLIED = NONE (RECO2 gagne, pas de capping appliqué) - Position actuelle : PL3_PL4 - Position finale : PL2_PL3
Interprétation : - RECO1 proposait 11,50€ (+15%) mais a été cappée à 10,50€ (+5%) par le capping sensibilité - RECO2 proposait 10,83€ (+8,3%) sans capping - RECO2 a gagné car plus agressive que RECO1 cappée - Le capping sensibilité a limité RECO1 mais n'a pas empêché une hausse de 8,3% via RECO2
Exemple 2 : Cascade avec capping basiques actif¶
Contexte : - Article : Produit basique (LC_ATTRIBUT = 'Basiques') - TYPE_CLIENT = RSI HM - TYPE_RESTAURANT = SOCIAL - GEO = NO - UNIVERS = ZOOM1
Données initiales : - Prix actuel = 8,00€ - Position actuelle = PL5_PL6 - NEW_PAS = 5,00€ - NEW_PRB = 12,00€ - NEW_BORNE_PL2_PL3 = 9,50€ - PRICE_SENSITIVITY = LOW - LC_ATTRIBUT = 'Basiques'
Capping configuré : - CAPPING_LOW = 0,20 (20%) - Capping basiques = 0,50 (50%)
Calcul étape par étape :
1. RECO1_BASE : - Position = PL5_PL6 - Règle = Remonter vers PL5 (borne PL5_PL6) - RECO1_BASE = 10,50€ (exemple) - Hausse brute = +31,25%
2. RECO1_APRES_CAPPING_SENSIBILITE : - Sensibilité = LOW - Capping = 20% - Prix max autorisé = 8,00€ × 1,20 = 9,60€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(10,50€, 9,60€) = 9,60€ - Hausse après capping sensibilité = +20%
3. RECO1_AVEC_CAPPING (cascade basiques) : - LC_ATTRIBUT = 'Basiques' ✓ - Prix max basiques = 8,00€ × 1,50 = 12,00€ - RECO1_AVEC_CAPPING = MIN(9,60€, 12,00€) = 9,60€ - Le capping basiques (50%) est moins restrictif que le capping sensibilité (20%) - Le capping sensibilité reste le plus contraignant
4. RECO2 : - Hausse PAS = +10% (exemple) - RECO2 = 8,00€ × 1,10 = 8,80€
5. Sélection finale (CHEMIN 3) : - MAX(9,60€, 8,80€) = 9,60€ - RECO_SELECTIONNEE = RECO1_REPOSITIONNEMENT_PALIERS
6. Capping PRB : - 9,60€ < 12,00€ → OK
Résultat final : - Prix recommandé : 9,60€ - Hausse finale : +20% - CAPPING_APPLIED = SENSIBILITE (le capping sensibilité était le plus restrictif) - Note : Même si c'est un produit basique, le capping basiques (50%) n'était pas le plus contraignant
Interprétation : - RECO1_BASE = 10,50€ (+31,25%) trop agressif - Capping sensibilité (LOW = 20%) ramène à 9,60€ - Capping basiques (50%) aurait permis jusqu'à 12,00€ - C'est le capping sensibilité qui a limité la hausse, pas le capping basiques
Exemple 3 : Capping basiques devient déterminant¶
Contexte : - Article : Produit basique sensibilité MEDIUM - Prix actuel = 6,00€
Données : - RECO1_BASE = 11,00€ (hausse brute +83%) - PRICE_SENSITIVITY = MEDIUM - CAPPING_MEDIUM = 0,30 (30%) - LC_ATTRIBUT = 'Basiques'
Calcul :
1. RECO1_BASE = 11,00€
2. RECO1_APRES_CAPPING_SENSIBILITE : - Prix max sensibilité = 6,00€ × 1,30 = 7,80€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(11,00€, 7,80€) = 7,80€
3. RECO1_AVEC_CAPPING (cascade basiques) : - Prix max basiques = 6,00€ × 1,50 = 9,00€ - RECO1_AVEC_CAPPING = MIN(7,80€, 9,00€) = 7,80€ - Capping sensibilité toujours plus restrictif
Résultat : - Prix recommandé : 7,80€ (+30%) - CAPPING_APPLIED = SENSIBILITE
Scénario alternatif (CAPPING_MEDIUM = 0,60 = 60%) :
2. RECO1_APRES_CAPPING_SENSIBILITE : - Prix max sensibilité = 6,00€ × 1,60 = 9,60€ - RECO1_APRES_CAPPING_SENSIBILITE = MIN(11,00€, 9,60€) = 9,60€
3. RECO1_AVEC_CAPPING (cascade basiques) : - Prix max basiques = 6,00€ × 1,50 = 9,00€ - RECO1_AVEC_CAPPING = MIN(9,60€, 9,00€) = 9,00€ ✓ - Le capping basiques devient le plus restrictif
Résultat alternatif : - Prix recommandé : 9,00€ (+50%) - CAPPING_APPLIED = BASIQUES_50PCT
Interprétation : - Le capping basiques n'est déterminant que si le capping sensibilité autorise une hausse > 50% - Dans la pratique, avec des cappings sensibilité typiques (HIGH=5%, MEDIUM=15%, LOW=20%), le capping basiques n'est que rarement le plus restrictif - Il sert de filet de sécurité pour les cas extrêmes où RECO1_BASE serait très agressive
Exemple 4 : CHEMIN 2 avec plancher actif¶
Contexte : - Client premium en PL1 des anciennes bornes - Corridor qui remonte (bornes PT1CE optimisées)
Données initiales : - Prix actuel = 13,00€ - BORNE_PL1_PL2 (anciennes) = 12,00€ - PRB_ACTIF = 15,00€ - → Prix en PL1 anciennes ✓ (13,00€ > 12,00€ et 13,00€ ≤ 15,00€) - NEW_BORNE_PL2_PL3 = 13,50€ (remonte) - NEW_PRB = 16,00€
Calcul :
1. Arbre de décision : - Prix dans PL1 anciennes ✓ - → CHEMIN 2 : PL1_CONSERVATION_PREMIUM
2. Application plancher : - Prix actuel = 13,00€ - Plancher PL2_PL3 = 13,50€ - GREATEST(13,00€, 13,50€) = 13,50€ - Plancher actif ✓
3. Capping PRB : - 13,50€ < 16,00€ → OK
Résultat final : - Prix actuel : 13,00€ - Prix recommandé : 13,50€ - Hausse : +3,8% - DECISION_PATH = PL1_CONSERVATION_PREMIUM - RECO_SELECTIONNEE = CONSERVATION_PREMIUM - CAPPING_APPLIED = PLANCHER_PL2_PL3
Interprétation : - Client premium maintenu en position haute - Plancher de sécurité appliqué car le corridor a remonté - Évite la compression de marge du client premium
Exemple 5 : CHEMIN 1 - Gel prix (PAS en baisse)¶
Contexte : - PAS en baisse (coût d'achat réduit)
Données : - Prix actuel = 10,00€ - PAS_ACTIF = 7,50€ - NEW_PAS = 7,00€ (baisse de 0,50€) - NEW_PRB = 12,00€
Calcul :
1. Arbre de décision : - NEW_PAS (7,00€) < PAS_ACTIF (7,50€) ✓ - → CHEMIN 1 : PAS_BAISSE_GEL_PRIX
2. Action : - Prix recommandé = Prix actuel = 10,00€ - Hausse = 0%
Résultat final : - Prix recommandé : 10,00€ (inchangé) - DECISION_PATH = PAS_BAISSE_GEL_PRIX - RECO_SELECTIONNEE = GEL_PRIX - CAPPING_APPLIED = GEL_PAS - PCT_HAUSSE_FINALE = 0%
Interprétation : - Baisse de coût d'achat non répercutée au client - Amélioration de la marge sans toucher au prix - Tous les calculs de RECO1/RECO2 sont ignorés
Requêtes de diagnostic et d'analyse¶
Diagnostic 1 : Vérifier les cappings appliqués par cube¶
Objectif : S'assurer que tous les cubes ont des cappings configurés.
Requête :
SELECT
UNIVERS,
TYPE_CLIENT,
TYPE_RESTAURANT,
GEO,
CUBE_TYPE,
CAPPING_HIGH,
CAPPING_MEDIUM,
CAPPING_LOW
FROM PT2QE_CAPPING_CUBES
WHERE UNIVERS = 'ZOOM1'
ORDER BY TYPE_CLIENT, TYPE_RESTAURANT, GEO;
Analyse : - Vérifier qu'aucun capping n'est NULL - Vérifier la cohérence : CAPPING_HIGH ≤ CAPPING_MEDIUM ≤ CAPPING_LOW - Identifier les cubes avec cappings atypiques
Diagnostic 2 : Distribution des cappings appliqués¶
Objectif : Comprendre quels cappings sont les plus contraignants.
Requête :
SELECT
CAPPING_APPLIED,
COUNT(*) as NB_OFFRES,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 1) as PCT_OFFRES,
ROUND(AVG(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MOY_PCT,
ROUND(MIN(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MIN_PCT,
ROUND(MAX(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MAX_PCT
FROM PT2QE_RECOMMENDATIONS
GROUP BY CAPPING_APPLIED
ORDER BY NB_OFFRES DESC;
Lecture : - Si SENSIBILITE domine (>40%) → Cappings sensibilité bien calibrés - Si NONE domine (>60%) → Cappings peut-être trop permissifs - Si PRB_FINAL élevé (>20%) → Corridors compressés, problème structurel - Si BASIQUES_50PCT > 5% → Beaucoup de produits basiques avec hausses agressives
Diagnostic 3 : Impact du capping sensibilité¶
Objectif : Mesurer l'efficacité du capping sensibilité.
Requête :
SELECT
PRICE_SENSITIVITY,
COUNT(*) as NB_OFFRES,
-- Cas où le capping sensibilité a limité
SUM(CASE
WHEN RECO1_BASE > RECO1_APRES_CAPPING_SENSIBILITE
THEN 1 ELSE 0
END) as NB_CAPPEES_SENSIBILITE,
ROUND(SUM(CASE
WHEN RECO1_BASE > RECO1_APRES_CAPPING_SENSIBILITE
THEN 1 ELSE 0
END) * 100.0 / COUNT(*), 1) as PCT_CAPPEES,
-- Réduction moyenne apportée par le capping
ROUND(AVG(RECO1_BASE - RECO1_APRES_CAPPING_SENSIBILITE), 2) as REDUCTION_MOY_EUROS,
ROUND(AVG((RECO1_BASE - RECO1_APRES_CAPPING_SENSIBILITE) / NULLIF(PRIX_TARIF_ACTUEL, 0)) * 100, 2) as REDUCTION_MOY_PCT
FROM PT2QE_RECOMMENDATIONS
WHERE DECISION_PATH = 'OPTIMISATION_STANDARD'
GROUP BY PRICE_SENSITIVITY
ORDER BY PRICE_SENSITIVITY;
Interprétation : - PCT_CAPPEES > 60% pour HIGH → Capping très actif (normal) - PCT_CAPPEES > 40% pour MEDIUM → Capping actif - PCT_CAPPEES > 20% pour LOW → Capping actif même sur sensibilité faible - REDUCTION_MOY_EUROS > 2€ → Capping très contraignant
Diagnostic 4 : Analyse de la cascade basiques¶
Objectif : Identifier l'impact du capping basiques (50%).
Requête :
SELECT
LC_ATTRIBUT,
COUNT(*) as NB_OFFRES,
-- Cas où le capping basiques a été plus restrictif que le capping sensibilité
SUM(CASE
WHEN LC_ATTRIBUT = 'Basiques'
AND RECO1_APRES_CAPPING_SENSIBILITE > PRIX_TARIF_ACTUEL * 1.50
THEN 1 ELSE 0
END) as NB_CAPPEES_BASIQUES,
ROUND(AVG(CASE
WHEN LC_ATTRIBUT = 'Basiques'
THEN PCT_HAUSSE_FINALE * 100
END), 2) as HAUSSE_MOY_BASIQUES_PCT,
ROUND(MAX(CASE
WHEN LC_ATTRIBUT = 'Basiques'
THEN PCT_HAUSSE_FINALE * 100
END), 2) as HAUSSE_MAX_BASIQUES_PCT
FROM PT2QE_RECOMMENDATIONS
WHERE DECISION_PATH = 'OPTIMISATION_STANDARD'
GROUP BY LC_ATTRIBUT
ORDER BY LC_ATTRIBUT;
Interprétation : - Si HAUSSE_MAX_BASIQUES_PCT proche de 50% → Capping basiques actif - Si NB_CAPPEES_BASIQUES > 0 → Certains produits basiques dépassaient 50% avec capping sensibilité - Si HAUSSE_MAX_BASIQUES_PCT > 50% → Problème : le capping basiques n'a pas fonctionné
Diagnostic 5 : Comparer RECO1 vs RECO2¶
Objectif : Comprendre la compétition entre les deux recommandations.
Requête :
SELECT
RECO_SELECTIONNEE,
COUNT(*) as NB_OFFRES,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 1) as PCT_OFFRES,
ROUND(AVG(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MOY_PCT,
ROUND(AVG(RECO1_AVEC_CAPPING), 2) as RECO1_CAPPED_MOY,
ROUND(AVG(RECO2), 2) as RECO2_MOY,
ROUND(AVG(RECO2 - RECO1_AVEC_CAPPING), 2) as ECART_MOYEN_EUROS
FROM PT2QE_RECOMMENDATIONS
WHERE DECISION_PATH = 'OPTIMISATION_STANDARD'
GROUP BY RECO_SELECTIONNEE
ORDER BY RECO_SELECTIONNEE;
Interprétation : - Si RECO1 > 80% → Paliers très agressifs, cappings limitent fort - Si RECO2 > 50% → Hausse PAS très importante ou cappings trop restrictifs sur RECO1 - ECART_MOYEN_EUROS positif quand RECO2 gagne → RECO2 systématiquement plus haute
Diagnostic 6 : Analyse par chemin de décision¶
Objectif : Comprendre la répartition entre les 3 chemins.
Requête :
SELECT
DECISION_PATH,
RECO_SELECTIONNEE,
COUNT(*) as NB_OFFRES,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 1) as PCT_TOTAL,
ROUND(AVG(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MOY_PCT,
ROUND(MEDIAN(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MEDIANE_PCT,
COUNT(DISTINCT ID_CLN) as NB_CLIENTS,
COUNT(DISTINCT ID_ART) as NB_ARTICLES
FROM PT2QE_RECOMMENDATIONS
GROUP BY DECISION_PATH, RECO_SELECTIONNEE
ORDER BY DECISION_PATH, RECO_SELECTIONNEE;
Interprétation : - CHEMIN 1 (GEL_PRIX) > 10% → Beaucoup de PAS en baisse (inhabituel) - CHEMIN 2 (CONSERVATION_PREMIUM) entre 5-15% → Normal - CHEMIN 3 (OPTIMISATION_STANDARD) > 70% → Comportement standard - HAUSSE_MOY_PCT (CHEMIN 2) < 5% → Conservation fonctionne bien
Diagnostic 7 : Offres problématiques (hausses excessives)¶
Objectif : Identifier les offres avec hausses > 20%.
Requête :
SELECT
ID_CLN,
LC_CLN,
ID_ART,
LC_ART,
TYPE_CLIENT,
TYPE_RESTAURANT,
UNIVERS,
LC_ATTRIBUT,
PRIX_TARIF_ACTUEL,
PRIX_RECOMMANDE,
ROUND(PCT_HAUSSE_FINALE * 100, 2) as PCT_HAUSSE,
DECISION_PATH,
RECO_SELECTIONNEE,
CAPPING_APPLIED,
PRICE_SENSITIVITY,
RECO1_BASE,
RECO1_AVEC_CAPPING,
RECO2
FROM PT2QE_RECOMMENDATIONS
WHERE PCT_HAUSSE_FINALE > 0.20 -- Plus de 20%
ORDER BY PCT_HAUSSE_FINALE DESC
FETCH FIRST 100 ROWS ONLY;
Analyse : - Vérifier LC_ATTRIBUT : Si 'Basiques', hausse jusqu'à 50% acceptable - Vérifier CAPPING_APPLIED : Si NONE, identifier pourquoi aucun capping - Vérifier RECO_SELECTIONNEE : Si RECO2, hausse PAS très élevée - Identifier TYPE_CLIENT/TYPE_RESTAURANT pour ajustement ciblé
Diagnostic 8 : Vérifier la couverture des cappings¶
Objectif : S'assurer que tous les cubes trouvés dans les recommandations ont des cappings.
Requête :
SELECT
r.UNIVERS,
r.TYPE_CLIENT,
r.TYPE_RESTAURANT,
r.GEO,
COUNT(*) as NB_OFFRES,
c.CAPPING_HIGH,
c.CAPPING_MEDIUM,
c.CAPPING_LOW,
c.CUBE_TYPE
FROM PT2QE_RECOMMENDATIONS r
LEFT JOIN PT2QE_CAPPING_CUBES 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')
GROUP BY
r.UNIVERS, r.TYPE_CLIENT, r.TYPE_RESTAURANT, r.GEO,
c.CAPPING_HIGH, c.CAPPING_MEDIUM, c.CAPPING_LOW, c.CUBE_TYPE
HAVING c.CAPPING_HIGH IS NULL -- Cubes sans capping
ORDER BY NB_OFFRES DESC;
Interprétation :
- Si résultat non vide → Certains cubes n'ont pas de capping (problème)
- Vérifier le fichier inputs/capping_type_client.csv pour ces TYPE_CLIENT
- Ajouter les lignes manquantes et relancer
Diagnostic 9 : Comparer avant/après ajustement¶
Objectif : Mesurer l'impact d'un ajustement de capping (après option 2).
Requête (à exécuter sur les deux versions) :
-- Version initiale (outputs/run_*)
SELECT
'AVANT' as VERSION,
COUNT(*) as NB_OFFRES,
ROUND(AVG(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MOY_PCT,
ROUND(MEDIAN(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MEDIANE_PCT,
ROUND(MIN(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MIN_PCT,
ROUND(MAX(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MAX_PCT,
SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.15 THEN 1 ELSE 0 END) as NB_PLUS_15PCT,
ROUND(SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.15 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) as PCT_PLUS_15PCT
FROM PT2QE_RECOMMENDATIONS;
-- Version après corrections (outputs/corrections_*)
-- (même requête avec VERSION = 'APRES')
Comparaison :
VERSION | HAUSSE_MOY_PCT | HAUSSE_MEDIANE_PCT | PCT_PLUS_15PCT
--------|----------------|--------------------|--------------
AVANT | 6.2 | 5.5 | 5.2%
APRES | 5.1 | 4.8 | 2.1%
Interprétation : - Réduction hausse moyenne : -1,1 points - Réduction offres > 15% : -3,1 points - Impact positif de l'ajustement
Règles de validation et points d'attention¶
Validation 1 : Cohérence des cappings¶
Règle : CAPPING_HIGH ≤ CAPPING_MEDIUM ≤ CAPPING_LOW
Vérification :
SELECT *
FROM PT2QE_CAPPING_CUBES
WHERE CAPPING_HIGH > CAPPING_MEDIUM
OR CAPPING_MEDIUM > CAPPING_LOW;
Action si non-respect : Corriger le fichier inputs/capping_type_client.csv ou corrections/capping_cubes_corrections.csv.
Validation 2 : Valeurs de capping dans les limites acceptables¶
Règle : 0 ≤ Capping ≤ 1 (0% à 100%)
Vérification :
SELECT *
FROM PT2QE_CAPPING_CUBES
WHERE CAPPING_HIGH < 0 OR CAPPING_HIGH > 1
OR CAPPING_MEDIUM < 0 OR CAPPING_MEDIUM > 1
OR CAPPING_LOW < 0 OR CAPPING_LOW > 1;
Action si non-respect : Corriger les valeurs erronées.
Validation 3 : Prix recommandé ≥ PAS¶
Règle : Aucun prix recommandé ne doit être inférieur au PAS (sauf cas extrêmes de compression).
Vérification :
SELECT
ID_CLN,
ID_ART,
PRIX_RECOMMANDE,
NEW_PAS,
DECISION_PATH,
PRIX_RECOMMANDE - NEW_PAS as ECART_PAS
FROM PT2QE_RECOMMENDATIONS
WHERE PRIX_RECOMMANDE < NEW_PAS;
Action si non-respect : - Si quelques cas (< 1%) → Acceptable (arrondis, cas limites) - Si nombreux cas (> 5%) → Problème structurel, contacter support
Validation 4 : Prix recommandé ≤ PRB¶
Règle : Aucun prix ne doit dépasser le PRB (capping PRB final obligatoire).
Vérification :
SELECT
ID_CLN,
ID_ART,
PRIX_RECOMMANDE,
NEW_PRB,
DECISION_PATH,
PRIX_RECOMMANDE - NEW_PRB as DEPASSEMENT
FROM PT2QE_RECOMMENDATIONS
WHERE PRIX_RECOMMANDE > NEW_PRB;
Action si non-respect : - Si résultat non vide → Bug dans le calcul, contacter support - Le capping PRB final doit TOUJOURS s'appliquer
Validation 5 : Cohérence hausse finale vs. RECO sélectionnée¶
Règle : La hausse finale doit correspondre à la RECO sélectionnée.
Vérification :
SELECT
COUNT(*) as NB_INCOHERENCES
FROM PT2QE_RECOMMENDATIONS
WHERE (
RECO_SELECTIONNEE = 'RECO1_REPOSITIONNEMENT_PALIERS'
AND ABS(PRIX_RECOMMANDE - RECO1_AVEC_CAPPING) > 0.01
AND CAPPING_APPLIED != 'PRB_FINAL'
)
OR (
RECO_SELECTIONNEE = 'RECO2_HAUSSE_PROPORTIONNELLE_PAS'
AND ABS(PRIX_RECOMMANDE - RECO2) > 0.01
AND CAPPING_APPLIED != 'PRB_FINAL'
);
Action si non-respect : - Si > 0 → Vérifier la logique de sélection - Tolérance de 0,01€ pour les arrondis
Validation 6 : Produits basiques ne dépassent pas +50%¶
Règle : LC_ATTRIBUT = 'Basiques' → Hausse ≤ 50%
Vérification :
SELECT
ID_CLN,
ID_ART,
LC_ART,
PRIX_TARIF_ACTUEL,
PRIX_RECOMMANDE,
ROUND(PCT_HAUSSE_FINALE * 100, 2) as PCT_HAUSSE,
CAPPING_APPLIED
FROM PT2QE_RECOMMENDATIONS
WHERE LC_ATTRIBUT = 'Basiques'
AND PCT_HAUSSE_FINALE > 0.50;
Action si non-respect : - Si résultat non vide et CAPPING_APPLIED != 'PRB_FINAL' → Bug, contacter support - Si CAPPING_APPLIED = 'PRB_FINAL' → Acceptable (PRB a priorité sur capping basiques)
Validation 7 : CHEMIN 1 avec hausse = 0%¶
Règle : DECISION_PATH = 'PAS_BAISSE_GEL_PRIX' → PCT_HAUSSE_FINALE = 0
Vérification :
SELECT *
FROM PT2QE_RECOMMENDATIONS
WHERE DECISION_PATH = 'PAS_BAISSE_GEL_PRIX'
AND PCT_HAUSSE_FINALE != 0;
Action si non-respect : Bug dans l'arbre de décision, contacter support.
Validation 8 : CHEMIN 2 avec plancher respecté¶
Règle : DECISION_PATH = 'PL1_CONSERVATION_PREMIUM' → PRIX_RECOMMANDE ≥ NEW_BORNE_PL2_PL3 (sauf si PRB < plancher)
Vérification :
SELECT
ID_CLN,
ID_ART,
PRIX_RECOMMANDE,
NEW_BORNE_PL2_PL3,
NEW_PRB,
CAPPING_APPLIED
FROM PT2QE_RECOMMENDATIONS
WHERE DECISION_PATH = 'PL1_CONSERVATION_PREMIUM'
AND PRIX_RECOMMANDE < NEW_BORNE_PL2_PL3
AND PRIX_RECOMMANDE < NEW_PRB; -- Exclure les cas où PRB < plancher
Action si non-respect : Bug dans l'application du plancher, contacter support.
Validation 9 : Distribution des hausses cohérente¶
Règle métier : Aucune recommandation formelle, mais des fourchettes indicatives : - < 5% des offres avec hausse > 20% - < 15% des offres avec hausse > 15% - Hausse moyenne entre 3% et 8%
Vérification :
SELECT
COUNT(*) as TOTAL_OFFRES,
SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.20 THEN 1 ELSE 0 END) as NB_PLUS_20PCT,
ROUND(SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.20 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) as PCT_PLUS_20,
SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.15 THEN 1 ELSE 0 END) as NB_PLUS_15PCT,
ROUND(SUM(CASE WHEN PCT_HAUSSE_FINALE > 0.15 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) as PCT_PLUS_15,
ROUND(AVG(PCT_HAUSSE_FINALE) * 100, 2) as HAUSSE_MOY_PCT
FROM PT2QE_RECOMMENDATIONS;
Action si non-respect : - Analyser les offres concernées (requête Diagnostic 7) - Ajuster les cappings selon les besoins métier
Validation 10 : Tous les cubes ont des cappings¶
Règle : Chaque combinaison UNIVERS × TYPE_CLIENT × TYPE_RESTAURANT × GEO doit avoir des cappings.
Vérification : Voir Diagnostic 8.
Action si non-respect : Compléter inputs/capping_type_client.csv avec les TYPE_CLIENT manquants.
Points d'attention et pièges courants¶
Piège 1 : Confusion entre les niveaux de capping¶
Problème : Modifier corrections/capping_cubes_corrections.csv mais relancer l'option 1 au lieu de l'option 2.
Conséquence : Les corrections sont ignorées, le fichier inputs/capping_type_client.csv est utilisé.
Solution : - Option 1 = Nouveau calcul complet → Utilise niveau 2 (TYPE_CLIENT) - Option 2 = Ajustement → Utilise niveau 3 (corrections cubes)
Piège 2 : Modifier les clés du cube dans le fichier de corrections¶
Problème : Modifier UNIVERS, TYPE_CLIENT, TYPE_RESTAURANT ou GEO dans corrections/capping_cubes_corrections.csv.
Conséquence : La jointure avec PT2QE_RECOMMENDATIONS échoue, les corrections ne s'appliquent pas.
Solution : Ne jamais modifier les 4 premières colonnes, uniquement les colonnes CAPPING_*.
Piège 3 : Encodage incorrect du fichier CSV¶
Problème : Sauvegarder le CSV en UTF-8 au lieu de CP1252.
Conséquence : Caractères spéciaux mal interprétés, parsing échoué.
Solution : - Excel : "Enregistrer sous" > "CSV (séparateur : point-virgule)" → Encodage CP1252 automatique - Notepad++ : Menu "Encodage" > "Encoder en ANSI" avant sauvegarde
Piège 4 : Séparateur incorrect¶
Problème : Utiliser virgule (,) au lieu de point-virgule (;) comme séparateur.
Conséquence : Parsing échoué, colonnes mal interprétées.
Solution : Toujours utiliser point-virgule (;) comme séparateur de colonnes.
Piège 5 : Décimale incorrecte¶
Problème : Utiliser point (.) au lieu de virgule (,) comme séparateur décimal.
Conséquence : Valeurs mal interprétées (0.05 lu comme 0 ou erreur).
Solution : Toujours utiliser virgule (,) comme séparateur décimal dans les CSV.
Piège 6 : Cappings incohérents (HIGH > MEDIUM > LOW)¶
Problème : Définir CAPPING_HIGH = 0,10 et CAPPING_LOW = 0,05.
Conséquence : Logique inversée, sensibilité HIGH moins restrictive que LOW.
Solution : Respecter CAPPING_HIGH ≤ CAPPING_MEDIUM ≤ CAPPING_LOW.
Piège 7 : Oublier de créer le dossier corrections¶
Problème : Lancer l'option 2 sans avoir créé le dossier corrections/.
Conséquence : Erreur "Dossier corrections non trouvé".
Solution : Le menu crée automatiquement le dossier, mais vérifier qu'il contient bien le fichier capping_cubes_corrections.csv.
Piège 8 : Confondre PCT_HAUSSE_FINALE et les cappings¶
Problème : Penser que PCT_HAUSSE_FINALE ne peut jamais dépasser le capping configuré.
Conséquence : Surprise de voir des hausses de 8% alors que CAPPING_HIGH = 5%.
Explication : - Le capping limite RECO1, pas le prix final - RECO2 n'est jamais cappée - Si RECO2 > RECO1_cappée, c'est RECO2 qui gagne - Le prix final peut donc dépasser le capping si RECO2 est agressive
Solution : Accepter que le capping soit un outil de limitation de RECO1, pas une garantie absolue de la hausse finale.
Piège 9 : Sur-itération des ajustements¶
Problème : Ajuster les cappings 10 fois de suite pour atteindre une cible précise.
Conséquence : Sur-calibrage, perte de sens des paramètres, instabilité.
Solution : - Limiter à 3-4 itérations maximum - Accepter une marge de tolérance (ex: hausse moyenne entre 5-6% plutôt qu'exactement 5,5%) - Si impossibilité d'atteindre la cible → Revoir la stratégie globale plutôt que les cappings
Piège 10 : Ignorer l'analyse des chemins de décision¶
Problème : Se concentrer uniquement sur la distribution des hausses sans analyser les chemins.
Conséquence : Ajustements de cappings inefficaces (ex: ajuster pour CHEMIN 2 alors que le problème vient du PAS).
Solution : Toujours analyser decision_path_analysis.csv avant d'ajuster les cappings.
Résumé du processus complet¶
- Préparer le fichier de capping :
inputs/capping_type_client.csv - Lancer l'option 1 : Calcul complet avec cappings niveau 2
- Analyser les résultats : Fichiers CSV dans
outputs/run_* - Décider :
- Résultats OK → Option 3 (génération finale)
- Ajustement global nécessaire → Modifier niveau 2 et relancer option 1
- Ajustement ciblé nécessaire → Créer niveau 3 et lancer option 2
- Répéter étapes 3-4 si nécessaire (max 3-4 itérations)
- Générer les offres finales : Option 3
Durée totale du processus : Variable selon le nombre d'itérations.
Livrables finaux :
- outputs/final_*/final_price_offers.csv : Offres client × article prêtes à l'emploi
- outputs/final_*/validation_report.csv : Rapport de validation
- outputs/final_*/export_summary.txt : Résumé statistique