Aller au contenu

Enrichissement et mapping - PT2QE

Vue d'ensemble

PT2QE enrichit chaque offre de prix (client × article) avec 5 dimensions clés avant de calculer les recommandations :

  1. FG_HM : Flag hors mercuriale ('0' ou '1')
  2. UNIVERS : Périmètre (ZOOM1/ZOOM2/ZOOM3)
  3. TYPE_CLIENT : Type client normalisé
  4. TYPE_RESTAURANT : Type restaurant normalisé
  5. GEO : Zone géographique

Ces dimensions permettent ensuite de matcher chaque offre avec son corridor PT1CE correspondant.

⚠️ IMPORTANT : PT2QE nécessite que PT1CE ait été exécuté AU PRÉALABLE pour que les tables PT1CE_OPTIMAL_* existent.

🔒 PÉRIMÈTRE ACTUEL : PT2QE traite UNIQUEMENT les offres ZOOM1. Les offres ZOOM2 et ZOOM3 sont extraites mais exclues du calcul.


Scope temporel de l'enrichissement

Période d'analyse

L'enrichissement utilise l'historique transactionnel des 4 derniers trimestres fiscaux COMPLETS :

  • Source : SYS_MD_CALENDRIER_SYSCO
  • Logique : Trimestres terminés dont la dernière semaine (MAX(ID_SEM)) est antérieure à la date d'exécution
  • Module : utils/period_manager.pyget_last_four_complete_fiscal_quarters()

Exemple d'exécution le 03/11/2025 :

Trimestre en cours : 2025_Q04 (non complet)
→ PT2QE utilise : 2025_Q03, 2025_Q02, 2025_Q01, 2024_Q04
→ Période : du 2024-04-01 au 2025-09-30

📍 Comment vérifier la période utilisée :

-- Derniers trimestres complets
SELECT
    ID_EXF || '_Q' || NO_TRF as QUARTER_CODE,
    MIN(ID_SEM) as START_DATE,
    MAX(ID_SEM) as END_DATE
FROM SYS_MD_CALENDRIER_SYSCO
WHERE MAX(ID_SEM) < SYSDATE
GROUP BY ID_EXF, NO_TRF
ORDER BY ID_EXF DESC, NO_TRF DESC
FETCH FIRST 4 ROWS ONLY;

⚠️ Si erreur "Impossible de trouver 4 trimestres complets" : - Le calendrier fiscal manque de données historiques - Contacter l'équipe data pour charger des trimestres passés


1. Récupération du FG_HM historique

Concept

FG_HM = Flag Hors Mercuriale

  • '0' : Offre mercuriale (tarif catalogue standard)
  • '1' : Offre hors mercuriale (conditions spéciales négociées)

Nature : Donnée dynamique récupérée depuis l'historique transactionnel (dernière transaction connue).

Extraction SQL

Requête complète (dans extract_price_offers.py) :

WITH LAST_FG_HM AS (
    SELECT 
        ID_CLN_KEY,
        ID_CLN,
        ID_ART,
        FG_HM as LAST_FG_HM,
        ID_MERC_HM
    FROM (
        SELECT 
            f.ID_CLN_KEY,
            c.ID_CLN,
            f.ID_ART,

            -- Standardisation FG_HM
            CASE 
                WHEN TRIM(f.FG_HM) = 'X' THEN '1'
                ELSE '0'
            END AS FG_HM,

            TRIM(f.ID_MERC_HM) AS ID_MERC_HM,

            -- Sélection dernière transaction
            ROW_NUMBER() OVER (
                PARTITION BY c.ID_CLN, f.ID_ART 
                ORDER BY f.DT_CDE DESC, f.ID_FAC DESC
            ) as RN

        FROM SYS_FACTURE_LIGNE f
        JOIN SYS_MD_CLIENT c ON f.ID_CLN_KEY = c.ID_CLN_KEY
        JOIN SYS_MD_ARTICLE a ON f.ID_ART = a.ID_ART
        LEFT JOIN PRP_LABELS p ON f.ID_PRP = p.ID_PRP_KEY

        WHERE f.DT_CDE BETWEEN {start_date} AND {end_date}
            AND UPPER(TRIM(c.ID_TC_CG)) <> 'AUTRES'
            AND a.ID_GMM <> 'PSN'
            AND a.LC_HIC_SYSCO_N2 NOT IN ('Divers', 'Freezer')
            AND COALESCE(TRIM(f.FG_PRESTA), '0') = '0'
            AND COALESCE(TRIM(f.FG_MARCHANDISE), ' ') IN ('X', '1')
            AND f.MT_GM4 IS NOT NULL
            AND f.MT_CAB > 0
            AND f.QT_UF > 0
            AND p.ID_PRP_KEY IS NOT NULL  -- Exclut prix promo
    )
    WHERE RN = 1  -- Garde uniquement la dernière transaction
)

Filtres appliqués :

Filtre Valeur Raison
ID_TC_CG <> 'AUTRES' Exclusion clients hors périmètre
ID_GMM <> 'PSN' Exclusion gamme Personnel
LC_HIC_SYSCO_N2 NOT IN ('Divers', 'Freezer') Exclusion catégories non standards
FG_PRESTA = '0' Exclusion prestations
FG_MARCHANDISE IN ('X', '1') Marchandise uniquement
MT_CAB > 0 CA positif
QT_UF > 0 Quantité positive
Prix promo Exclus via PRP_LABELS Focus sur prix catalogue

📍 Comment vérifier le FG_HM d'un client×article :

-- Dernière valeur FG_HM connue
SELECT 
    c.ID_CLN,
    c.LC_CLN,
    f.ID_ART,
    a.LC_ART,
    CASE WHEN TRIM(f.FG_HM) = 'X' THEN '1' ELSE '0' END as FG_HM,
    f.DT_CDE,
    f.ID_FAC
FROM SYS_FACTURE_LIGNE f
JOIN SYS_MD_CLIENT c ON f.ID_CLN_KEY = c.ID_CLN_KEY
JOIN SYS_MD_ARTICLE a ON f.ID_ART = a.ID_ART
WHERE c.ID_CLN = 'CLIENT123'
    AND f.ID_ART = 'ART456'
    AND f.DT_CDE >= ADD_MONTHS(SYSDATE, -12)
ORDER BY f.DT_CDE DESC, f.ID_FAC DESC
FETCH FIRST 1 ROW ONLY;

Cas particuliers FG_HM

Cas 1 : Client sans historique - Nouveau client ou client inactif - LAST_FG_HM reste NULL - Impact : Offre exclue du périmètre PT2QE (pas de mapping TYPE_CLIENT possible)

Cas 2 : Article jamais commandé par le client - LAST_FG_HM reste NULL - Impact : Offre exclue du périmètre PT2QE

Cas 3 : Changement de statut HM - Client passe de mercuriale ('0') à hors mercuriale ('1') - Comportement : PT2QE prend la valeur la plus récente - Effet : Le TYPE_CLIENT peut changer entre 2 exécutions

📍 Comment forcer un FG_HM spécifique :

PT2QE ne permet pas de forcer manuellement. La valeur provient TOUJOURS de l'historique.

Workaround si nécessaire : 1. Créer une transaction factice dans SYS_FACTURE_LIGNE avec le bon FG_HM 2. Relancer PT2QE


2. Calcul de l'UNIVERS

Définition

UNIVERS détermine le niveau de granularité du corridor :

  • ZOOM1 : Granularité maximale (4 dimensions : TYPE_CLIENT × TYPE_RESTAURANT × GEO × ID_ART)
  • ZOOM2 : Granularité intermédiaire
  • ZOOM3 : Granularité minimale (agrégation nationale)

⚠️ PT2QE VERSION ACTUELLE : Traite UNIQUEMENT ZOOM1

Règles de calcul

Module : extract_price_offers.py → CTE OFFERS_WITH_UNIVERS

Règles implémentées :

CASE
    -- ZOOM1 : RCI PI avec ou sans KAM
    WHEN ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'PINDEP' THEN 'ZOOM1'

    -- ZOOM1 : RCI GI SANS KAM
    WHEN ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GINDEP'
        AND ID_KAM = 'NO_KAM' THEN 'ZOOM1'

    -- ZOOM2 : RCI GI AVEC KAM
    WHEN ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GINDEP'
        AND ID_KAM <> 'NO_KAM' THEN 'ZOOM2'

    -- ZOOM1 : FG_HM = '1' (hors mercuriale) - HORS RSC
    WHEN FG_HM = '1' AND (
        (ID_TC_CG = 'RSI' AND ID_TC_CIBLE IN ('MP_AO_', 'GR_A_G', 'MPMAPA', 'SRCREG', 'CA_REG', 'CR_REG'))
        OR (ID_TC_CG = 'RCI' AND ID_TC_CIBLE IN ('PERSYS', 'PERCLI', 'AS_AUT'))
    ) THEN 'ZOOM1'

    -- ZOOM1 : RSC avec ID_MERC_HM = 'HM'
    WHEN ID_TC_CG = 'RSC' AND ID_TC_CIBLE IN ('CR_NAT', 'SRCNAT', 'MP_NAT', 'CA_NAT')
        AND TRIM(ID_MERC_HM) = 'HM' THEN 'ZOOM1'

    -- ZOOM2 : FG_HM = '0' (mercuriale)
    WHEN FG_HM = '0' AND (
        (ID_TC_CG = 'RSI' AND ID_TC_CIBLE IN ('MP_AO_', 'SRCREG', 'MPMAPA', 'CA_REG', 'CR_REG'))
        OR (ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GC_REG')
    ) THEN 'ZOOM2'

    -- ZOOM2 : RCI GC_REG avec FG_HM = '1'
    WHEN ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'GC_REG'
        AND FG_HM = '1' THEN 'ZOOM2'

    -- ZOOM3 : RSC avec ID_MERC_HM <> 'HM'
    WHEN ID_TC_CG = 'RSC' AND ID_TC_CIBLE IN ('SRCNAT', 'CR_NAT', 'MP_NAT', 'CA_NAT')
        AND TRIM(ID_MERC_HM) <> 'HM' THEN 'ZOOM3'

    -- ZOOM3 : RCC
    WHEN ID_TC_CG = 'RCC' AND ID_TC_CIBLE IN ('RCHNAT', 'GCN3PL', 'GCNDIR') THEN 'ZOOM3'

    ELSE 'HORS PERIMETRE'
END as UNIVERS

📍 Comment vérifier l'UNIVERS d'une offre :

SELECT 
    c.ID_CLN,
    c.LC_CLN,
    c.ID_TC_CG,
    c.ID_TC_CIBLE,
    fh.FG_HM,
    c.ID_KAM,
    fh.ID_MERC_HM,

    -- Calcul UNIVERS
    CASE
        WHEN c.ID_TC_CG = 'RCI' AND c.ID_TC_CIBLE = 'PINDEP' THEN 'ZOOM1'
        -- [autres règles...]
        ELSE 'HORS PERIMETRE'
    END as UNIVERS_CALCULE

FROM SYS_MD_CLIENT c
LEFT JOIN LAST_FG_HM fh ON c.ID_CLN = fh.ID_CLN
WHERE c.ID_CLN = 'CLIENT123';

📍 Comment ajouter une nouvelle règle UNIVERS :

  1. Éditer extract_price_offers.py
  2. Localiser la CTE OFFERS_WITH_UNIVERS
  3. Ajouter une clause WHEN dans le CASE

Exemple - ajouter RCI NOUVEAU_TYPE en ZOOM1 :

-- Ligne à ajouter dans le CASE
WHEN ID_TC_CG = 'RCI' AND ID_TC_CIBLE = 'NOUVEAU_TYPE' THEN 'ZOOM1'
  1. Relancer PT2QE Option 1

3. Enrichissement TYPE_CLIENT

Table de mapping

Table : PT0CE_TYPE_CLIENT_MAPPING

Structure :

Colonne Type Description
TYPE_CLIENT VARCHAR2(100) Type client normalisé (ex: "RCI PI GI")
UNIVERS VARCHAR2(10) ZOOM1/ZOOM2/ZOOM3
ID_TC_CG VARCHAR2(10) Code groupe client SAP
ID_TC_CIBLE VARCHAR2(10) Code cible client SAP
FG_HM VARCHAR2(1) '0' ou '1'
PRB NUMBER(1) 1=PRB_RC, 2=PRB_COLL

📍 Comment consulter les mappings existants :

-- Liste complète
SELECT 
    TYPE_CLIENT,
    UNIVERS,
    ID_TC_CG,
    ID_TC_CIBLE,
    FG_HM,
    PRB
FROM PT0CE_TYPE_CLIENT_MAPPING
ORDER BY UNIVERS, TYPE_CLIENT, FG_HM;

-- Compter par UNIVERS
SELECT 
    UNIVERS,
    COUNT(*) as NB_MAPPINGS,
    COUNT(DISTINCT TYPE_CLIENT) as NB_TYPE_CLIENT
FROM PT0CE_TYPE_CLIENT_MAPPING
GROUP BY UNIVERS
ORDER BY UNIVERS;

Processus de jointure

Module : extract_price_offers.py → jointure dans le SELECT final

SELECT 
    ou.*,
    COALESCE(tc.TYPE_CLIENT, 'Hors référentiel') AS TYPE_CLIENT,
    -- [autres colonnes...]
FROM OFFERS_WITH_UNIVERS ou
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
WHERE ou.UNIVERS = 'ZOOM1'  -- Filtre ZOOM1 immédiat
    AND tc.TYPE_CLIENT IS NOT NULL  -- Exclut offres non mappées

⚠️ Clé de jointure : - UNIVERS (calculé dynamiquement) - ID_TC_CG - ID_TC_CIBLE - FG_HM (depuis historique)

📍 Comment tester une jointure TYPE_CLIENT :

-- Test de jointure pour un client
SELECT 
    c.ID_CLN,
    c.LC_CLN,
    c.ID_TC_CG,
    c.ID_TC_CIBLE,
    fh.FG_HM,

    -- UNIVERS calculé (simpllifié ici)
    CASE 
        WHEN c.ID_TC_CG = 'RCI' AND c.ID_TC_CIBLE = 'PINDEP' THEN 'ZOOM1'
        ELSE 'AUTRE'
    END as UNIVERS,

    -- Résultat mapping
    tc.TYPE_CLIENT,
    tc.PRB

FROM SYS_MD_CLIENT c
LEFT JOIN LAST_FG_HM fh ON c.ID_CLN = fh.ID_CLN AND fh.ID_ART = 'ART123'
LEFT JOIN PT0CE_TYPE_CLIENT_MAPPING tc
    ON tc.UNIVERS = CASE WHEN c.ID_TC_CG = 'RCI' AND c.ID_TC_CIBLE = 'PINDEP' THEN 'ZOOM1' ELSE 'AUTRE' END
    AND tc.ID_TC_CG = c.ID_TC_CG
    AND tc.ID_TC_CIBLE = c.ID_TC_CIBLE
    AND tc.FG_HM = fh.FG_HM
WHERE c.ID_CLN = 'CLIENT123';

Modifier les mappings TYPE_CLIENT

📍 Ajouter un nouveau mapping :

INSERT INTO PT0CE_TYPE_CLIENT_MAPPING (
    TYPE_CLIENT,
    UNIVERS,
    ID_TC_CG,
    ID_TC_CIBLE,
    FG_HM,
    PRB
) VALUES (
    'NOUVEAU TYPE CLIENT',
    'ZOOM1',
    'RCI',
    'NOUVEAU',
    '0',  -- Mercuriale
    1     -- PRB_RC
);

COMMIT;

📍 Modifier un mapping existant :

UPDATE PT0CE_TYPE_CLIENT_MAPPING
SET TYPE_CLIENT = 'TYPE CLIENT MODIFIÉ'
WHERE UNIVERS = 'ZOOM1'
    AND ID_TC_CG = 'RCI'
    AND ID_TC_CIBLE = 'PINDEP'
    AND FG_HM = '0';

COMMIT;

📍 Supprimer un mapping :

DELETE FROM PT0CE_TYPE_CLIENT_MAPPING
WHERE UNIVERS = 'ZOOM1'
    AND ID_TC_CG = 'RCI'
    AND ID_TC_CIBLE = 'OBSOLETE';

COMMIT;

⚠️ Après modification : Relancer PT2QE Option 1 pour recalculer les recommandations.

Cas non mappés

Comportement : - Offres avec TYPE_CLIENT IS NULL ou 'Hors référentiel' - Exclues du périmètre PT2QE via le filtre WHERE tc.TYPE_CLIENT IS NOT NULL

📍 Identifier les offres non mappées :

-- Avant exclusion
SELECT 
    c.ID_TC_CG,
    c.ID_TC_CIBLE,
    fh.FG_HM,
    COUNT(*) as NB_OFFRES
FROM SYS_MD_CONDITION cnd
JOIN SYS_MD_CLIENT c ON cnd.ID_CLN_KEY = c.ID_CLN_KEY
LEFT JOIN LAST_FG_HM fh ON c.ID_CLN = fh.ID_CLN
LEFT JOIN PT0CE_TYPE_CLIENT_MAPPING tc
    ON tc.UNIVERS = 'ZOOM1'  -- Exemple ZOOM1
    AND tc.ID_TC_CG = c.ID_TC_CG
    AND tc.ID_TC_CIBLE = c.ID_TC_CIBLE
    AND tc.FG_HM = fh.FG_HM
WHERE tc.TYPE_CLIENT IS NULL
    AND cnd.FG_CND_VLD = 'X'
GROUP BY c.ID_TC_CG, c.ID_TC_CIBLE, fh.FG_HM
ORDER BY NB_OFFRES DESC;

4. Enrichissement TYPE_RESTAURANT

Table de mapping

Table : PT0CE_TYPE_RESTAURANT_MAPPING

Structure :

Colonne Type Description
LC_SFC_CIBLE VARCHAR2(100) Code sous-famille client SAP
Type_Restaurant VARCHAR2(100) Type restaurant normalisé

Exemples de valeurs :

LC_SFC_CIBLE Type_Restaurant
REST_TRAD Restaurant Traditionnel
REST_RAPIDE Restauration Rapide
CAFETERIA Cafétéria
BRASSERIE Brasserie
HOTEL Hôtellerie

📍 Comment consulter les mappings TYPE_RESTAURANT :

-- Liste complète
SELECT 
    LC_SFC_CIBLE,
    Type_Restaurant
FROM PT0CE_TYPE_RESTAURANT_MAPPING
ORDER BY Type_Restaurant;

-- Statistiques
SELECT 
    COUNT(*) as NB_TOTAL,
    COUNT(DISTINCT Type_Restaurant) as NB_TYPE_UNIQUES
FROM PT0CE_TYPE_RESTAURANT_MAPPING;

Processus de jointure

Jointure simple sur LC_SFC_CIBLE :

SELECT 
    ou.*,
    COALESCE(tr.Type_Restaurant, 'Hors référentiel') AS TYPE_RESTAURANT
FROM OFFERS_WITH_UNIVERS ou
LEFT JOIN PT0CE_TYPE_RESTAURANT_MAPPING tr
    ON tr.LC_SFC_CIBLE = ou.LC_SFC_CIBLE
WHERE ou.UNIVERS = 'ZOOM1'
    AND tr.Type_Restaurant IS NOT NULL;  -- Exclut offres non mappées

📍 Comment tester une jointure TYPE_RESTAURANT :

-- Test pour un client
SELECT 
    c.ID_CLN,
    c.LC_CLN,
    c.LC_SFC_CIBLE,
    tr.Type_Restaurant
FROM SYS_MD_CLIENT c
LEFT JOIN PT0CE_TYPE_RESTAURANT_MAPPING tr
    ON tr.LC_SFC_CIBLE = c.LC_SFC_CIBLE
WHERE c.ID_CLN = 'CLIENT123';

Modifier les mappings TYPE_RESTAURANT

📍 Ajouter un nouveau mapping :

INSERT INTO PT0CE_TYPE_RESTAURANT_MAPPING (
    LC_SFC_CIBLE,
    Type_Restaurant
) VALUES (
    'NOUVEAU_CODE',
    'Nouveau Type Restaurant'
);

COMMIT;

📍 Modifier un mapping existant :

UPDATE PT0CE_TYPE_RESTAURANT_MAPPING
SET Type_Restaurant = 'Type Restaurant Modifié'
WHERE LC_SFC_CIBLE = 'REST_TRAD';

COMMIT;

📍 Supprimer un mapping :

DELETE FROM PT0CE_TYPE_RESTAURANT_MAPPING
WHERE LC_SFC_CIBLE = 'CODE_OBSOLETE';

COMMIT;

⚠️ Après modification : Relancer PT2QE Option 1.

Cas non mappés

Comportement : - TYPE_RESTAURANT reste NULL ou 'Hors référentiel' - Exclues du périmètre PT2QE

📍 Identifier les LC_SFC_CIBLE non mappés :

SELECT 
    c.LC_SFC_CIBLE,
    COUNT(DISTINCT c.ID_CLN) as NB_CLIENTS
FROM SYS_MD_CLIENT c
LEFT JOIN PT0CE_TYPE_RESTAURANT_MAPPING tr
    ON tr.LC_SFC_CIBLE = c.LC_SFC_CIBLE
WHERE c.LC_SFC_CIBLE IS NOT NULL
    AND tr.Type_Restaurant IS NULL
GROUP BY c.LC_SFC_CIBLE
ORDER BY NB_CLIENTS DESC;

5. Enrichissement géographique (GEO)

Source de données

Table : SYS_MD_CLIENT.LC_ZDV_GRV

Extraction : Jointure directe, aucune table de mapping.

SELECT 
    c.ID_CLN,
    c.LC_ZDV_GRV as GEO
FROM SYS_MD_CLIENT c;

Valeurs GEO standards

Code GEO Région
IDF Île-de-France
NO Nord-Ouest
SO Sud-Ouest
SE Sud-Est
EST Est
RA Rhône-Alpes
NATIONAL National (agrégé)

📍 Comment consulter les GEO :

-- Distribution des GEO
SELECT 
    LC_ZDV_GRV as GEO,
    COUNT(DISTINCT ID_CLN) as NB_CLIENTS
FROM SYS_MD_CLIENT
WHERE LC_ZDV_GRV IS NOT NULL
GROUP BY LC_ZDV_GRV
ORDER BY NB_CLIENTS DESC;

Impact sur le matching corridors

ZOOM1/ZOOM2 : - GEO requis pour match MASTER - Si GEO IS NULL → fallback vers corridor NATIONAL

ZOOM3 : - GEO ignoré (corridors nationaux par défaut)

📍 Comment vérifier le GEO d'un client :

SELECT 
    ID_CLN,
    LC_CLN,
    LC_ZDV_GRV as GEO
FROM SYS_MD_CLIENT
WHERE ID_CLN = 'CLIENT123';

6. Matching avec les corridors PT1CE

Prérequis : Exécution PT1CE

⚠️ OBLIGATOIRE : PT1CE doit avoir été exécuté pour créer les tables suivantes :

  • PT1CE_OPTIMAL_ZOOM1
  • PT1CE_OPTIMAL_ZOOM2
  • PT1CE_OPTIMAL_ZOOM3

📍 Comment vérifier la présence des tables PT1CE :

-- Via PT2QE Menu - Option 5
-- Ou manuellement :
SELECT table_name
FROM user_tables
WHERE table_name LIKE 'PT1CE_OPTIMAL_%'
ORDER BY table_name;

Si tables manquantes : 1. Lancer PT1CE (menu START.bat dans dossier PT1CE) 2. Exécuter PT1CE Option 1 (Application nouveaux PAS/PRB) 3. Exécuter PT1CE Option 2 (Finalisation corridors) 4. Revenir à PT2QE

Stratégie de matching en cascade

Module : utils/corridor_matcher.pyenrich_offers_with_corridors()

2 tentatives de matching :

  1. MASTER : Match exact sur 4 dimensions
  2. NATIONAL : Fallback sur ID_ART uniquement

Implémentation SQL :

WITH CORRIDORS_ZOOM1_ONLY AS (
    -- Filtre ZOOM1 explicite (PT2QE actuel)
    SELECT * FROM PT1CE_OPTIMAL_ZOOM1
    WHERE STATUS = 'OPTIMAL'
),

-- TENTATIVE 1 : MASTER
MATCH_MASTER AS (
    SELECT 
        o.*,
        c.*,
        'MASTER' as MATCH_TYPE
    FROM PT2QE_PRICE_OFFERS o
    LEFT JOIN CORRIDORS_ZOOM1_ONLY c
        ON o.ID_ART = c.ID_ART
        AND o.TYPE_CLIENT = c.TYPE_CLIENT
        AND o.TYPE_RESTAURANT = c.TYPE_RESTAURANT
        AND NVL(o.GEO, 'NULL') = NVL(c.GEO, 'NULL')
        AND c.CUBE_TYPE = 'MASTER'
    WHERE c.ID_ART IS NOT NULL  -- Garde uniquement matchs trouvés
),

-- TENTATIVE 2 : NATIONAL (fallback)
MATCH_NATIONAL AS (
    SELECT 
        o.*,
        c.*,
        'NATIONAL' as MATCH_TYPE
    FROM PT2QE_PRICE_OFFERS o
    JOIN CORRIDORS_ZOOM1_ONLY c
        ON o.ID_ART = c.ID_ART
        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 (
        -- Uniquement si pas matché avec MASTER
        SELECT 1 FROM MATCH_MASTER m 
        WHERE m.ID_CLN = o.ID_CLN AND m.ID_ART = o.ID_ART
    )
),

-- Offres sans corridor
NO_MATCH AS (
    SELECT 
        o.*,
        CAST(NULL AS VARCHAR2(10)) as SOURCE_ZOOM,
        -- [autres colonnes NULL...]
        0 as HAS_CORRIDOR,
        'NO_MATCH' as MATCH_TYPE
    FROM PT2QE_PRICE_OFFERS o
    WHERE NOT EXISTS (SELECT 1 FROM MATCH_MASTER m WHERE m.ID_CLN = o.ID_CLN AND m.ID_ART = o.ID_ART)
        AND NOT EXISTS (SELECT 1 FROM MATCH_NATIONAL n WHERE n.ID_CLN = o.ID_CLN AND n.ID_ART = o.ID_ART)
)

-- Union finale
SELECT * FROM MATCH_MASTER
UNION ALL
SELECT * FROM MATCH_NATIONAL
UNION ALL
SELECT * FROM NO_MATCH;

📍 Comment vérifier le matching d'une offre :

-- Voir le type de match pour un client×article
SELECT 
    ID_CLN,
    LC_CLN,
    ID_ART,
    LC_ART,
    TYPE_CLIENT,
    TYPE_RESTAURANT,
    GEO,
    MATCH_TYPE,
    HAS_CORRIDOR,
    SOURCE_ZOOM
FROM PT2QE_PRICE_OFFERS_ENRICHED
WHERE ID_CLN = 'CLIENT123'
    AND ID_ART = 'ART456';

Statistiques de matching

Module : corridor_matcher.py_log_enhanced_matching_stats()

Métriques calculées :

SELECT
    MATCH_TYPE,
    COUNT(*) as NB_OFFRES,
    COUNT(DISTINCT ID_CLN) as NB_CLIENTS,
    COUNT(DISTINCT ID_ART) as NB_ARTICLES
FROM PT2QE_PRICE_OFFERS_ENRICHED
GROUP BY MATCH_TYPE
ORDER BY MATCH_TYPE;

Résultats typiques :

MATCH_TYPE Description % attendu
MASTER Match exact 4D 85-90%
NATIONAL Fallback agrégé 8-12%
NO_MATCH Aucun corridor 1-3%

📍 Comment afficher les stats après extraction :

Logs PT2QE Option 1 :

→ Résultats du matching :
  - MASTER : 45,230 offres, 1,250 clients, 3,420 articles
  - NATIONAL : 5,120 offres, 180 clients, 890 articles
  - NO_MATCH : 450 offres, 25 clients, 120 articles
→ Total : 50,800/50,800 offres avec corridor (100.0%)


7. Données récupérées depuis les corridors

Champs enrichis

Après matching, chaque offre hérite des données du corridor :

Anciennes bornes (PT0CE) : - PAS_ACTIF - PRB_RC_ACTIF / PRB_COLL_ACTIF - PRB_ACTIF (calculé selon PRB_TO_USE) - BORNE_PL1_PL2BORNE_PL6_PLX

Nouvelles bornes (PT1CE) : - NEW_PAS - NEW_PRB_RC / NEW_PRB_COLL - NEW_PRB (calculé selon PRB_TO_USE) - NEW_BORNE_PL1_PL2NEW_BORNE_PL6_PLX

Métriques : - PRICE_SENSITIVITY : HIGH/MEDIUM/LOW - ECART_TYPE : Écart-type des prix

📍 Comment consulter les données d'un corridor :

-- Corridor MASTER
SELECT 
    ID_ART,
    TYPE_CLIENT,
    TYPE_RESTAURANT,
    GEO,
    PAS_ACTIF,
    NEW_PAS,
    PRB_ACTIF,
    NEW_PRB,
    PRICE_SENSITIVITY
FROM PT1CE_OPTIMAL_ZOOM1
WHERE ID_ART = 'ART456'
    AND TYPE_CLIENT = 'RCI PI GI'
    AND CUBE_TYPE = 'MASTER';

8. Cas particuliers et gestion d'erreurs

Cas 1 : Nouveau client sans historique

Symptôme : Client créé récemment, aucune transaction.

Impact : - LAST_FG_HM reste NULL - Pas de mapping TYPE_CLIENT possible - Offres exclues du périmètre PT2QE

Diagnostic :

-- Clients sans historique transactionnel
SELECT 
    c.ID_CLN,
    c.LC_CLN,
    c.ID_TC_CG,
    c.ID_TC_CIBLE,
    cnd.NB_CONDITIONS
FROM SYS_MD_CLIENT c
JOIN (
    SELECT ID_CLN_KEY, COUNT(*) as NB_CONDITIONS
    FROM SYS_MD_CONDITION
    WHERE FG_CND_VLD = 'X'
    GROUP BY ID_CLN_KEY
) cnd ON c.ID_CLN_KEY = cnd.ID_CLN_KEY
LEFT JOIN LAST_FG_HM fh ON c.ID_CLN = fh.ID_CLN
WHERE fh.LAST_FG_HM IS NULL
ORDER BY cnd.NB_CONDITIONS DESC;

Solution : - Attendre que le client passe des commandes - PT2QE inclura automatiquement ses offres après historique disponible

Cas 2 : Client réactivé après inactivité

Symptôme : Client inactif pendant plusieurs trimestres, puis réactivé.

Comportement : - LAST_FG_HM = valeur de la dernière transaction connue (peut être ancienne) - Si transaction > 4 trimestres → FG_HM utilisé quand même

Diagnostic :

-- Clients avec historique ancien
SELECT 
    c.ID_CLN,
    c.LC_CLN,
    fh.FG_HM,
    fh.LAST_TRANSACTION_DATE,
    TRUNC(MONTHS_BETWEEN(SYSDATE, fh.LAST_TRANSACTION_DATE)) as MOIS_INACTIVITE
FROM SYS_MD_CLIENT c
JOIN (
    SELECT 
        ID_CLN,
        FG_HM,
        MAX(DT_CDE) as LAST_TRANSACTION_DATE
    FROM LAST_FG_HM
    GROUP BY ID_CLN, FG_HM
) fh ON c.ID_CLN = fh.ID_CLN
WHERE MONTHS_BETWEEN(SYSDATE, fh.LAST_TRANSACTION_DATE) > 12
ORDER BY MOIS_INACTIVITE DESC;

Impact : PT2QE utilise le FG_HM historique même ancien.

Cas 3 : Article sans corridor MASTER

Symptôme : Article nouveau ou rare, pas de corridor spécifique.

Comportement : 1. Tentative match MASTER → échec 2. Fallback vers corridor NATIONAL → recherche

Diagnostic :

-- Articles avec fallback NATIONAL
SELECT 
    ID_ART,
    LC_ART,
    COUNT(*) as NB_OFFRES_NATIONAL
FROM PT2QE_PRICE_OFFERS_ENRICHED
WHERE MATCH_TYPE = 'NATIONAL'
GROUP BY ID_ART, LC_ART
ORDER BY NB_OFFRES_NATIONAL DESC;

Solutions : - Option A : Attendre que PT1CE crée un corridor MASTER (plus de transactions nécessaires) - Option B : Utiliser le corridor NATIONAL existant (PT2QE le fait automatiquement)

Cas 4 : Enrichissement partiel

Symptôme : Certaines dimensions manquantes (TYPE_CLIENT NULL, GEO NULL, etc.)

Impact : Offre exclue du périmètre PT2QE.

Diagnostic :

-- Offres avec enrichissement incomplet
SELECT 
    'TYPE_CLIENT' as DIMENSION_MANQUANTE,
    COUNT(*) as NB_OFFRES
FROM PT2QE_PRICE_OFFERS
WHERE TYPE_CLIENT IS NULL OR TYPE_CLIENT = 'Hors référentiel'

UNION ALL

SELECT 
    'TYPE_RESTAURANT' as DIMENSION_MANQUANTE,
    COUNT(*) as NB_OFFRES
FROM PT2QE_PRICE_OFFERS
WHERE TYPE_RESTAURANT IS NULL OR TYPE_RESTAURANT = 'Hors référentiel'

UNION ALL

SELECT 
    'GEO' as DIMENSION_MANQUANTE,
    COUNT(*) as NB_OFFRES
FROM PT2QE_PRICE_OFFERS
WHERE GEO IS NULL
    AND UNIVERS IN ('ZOOM1', 'ZOOM2');

Solutions : 1. TYPE_CLIENT manquant : Ajouter un mapping dans PT0CE_TYPE_CLIENT_MAPPING 2. TYPE_RESTAURANT manquant : Ajouter un mapping dans PT0CE_TYPE_RESTAURANT_MAPPING 3. GEO manquant : Corriger LC_ZDV_GRV dans SYS_MD_CLIENT

Cas 5 : Aucun corridor PT1CE disponible

Symptôme : Tables PT1CE_OPTIMAL_* vides ou inexistantes.

Erreur :

[X] Tables PT1CE_OPTIMAL_* NON TROUVEES
PT2QE NECESSITE que PT1CE ait ete execute auparavant !

Solution : 1. Lancer PT1CE (START.bat dans dossier PT1CE) 2. Exécuter PT1CE Option 1 (Application nouveaux PAS/PRB) 3. Exécuter PT1CE Option 2 (Finalisation corridors) 4. Vérifier : PT2QE Menu → Option 5 (Vérifier prérequis) 5. Relancer PT2QE Option 1

Vérification manuelle :

SELECT COUNT(*) 
FROM PT1CE_OPTIMAL_ZOOM1
WHERE STATUS = 'OPTIMAL';
-- Doit retourner > 0

9. Procédures de maintenance

Mettre à jour les mappings TYPE_CLIENT

Fréquence recommandée : Avant chaque exécution PT2QE si nouveaux types clients SAP.

Étapes :

  1. Identifier les nouveaux types clients non mappés :
-- Types clients SAP présents mais non mappés
SELECT DISTINCT
    c.ID_TC_CG,
    c.ID_TC_CIBLE,
    COUNT(DISTINCT c.ID_CLN) as NB_CLIENTS
FROM SYS_MD_CLIENT c
LEFT JOIN PT0CE_TYPE_CLIENT_MAPPING tc
    ON tc.ID_TC_CG = c.ID_TC_CG
    AND tc.ID_TC_CIBLE = c.ID_TC_CIBLE
WHERE tc.TYPE_CLIENT IS NULL
    AND c.ID_TC_CG <> 'AUTRES'
GROUP BY c.ID_TC_CG, c.ID_TC_CIBLE
ORDER BY NB_CLIENTS DESC;
  1. Ajouter les nouveaux mappings :
-- Pour chaque combinaison trouvée
INSERT INTO PT0CE_TYPE_CLIENT_MAPPING (
    TYPE_CLIENT, UNIVERS, ID_TC_CG, ID_TC_CIBLE, FG_HM, PRB
) VALUES (
    'NOUVEAU TYPE',  -- À déterminer
    'ZOOM1',         -- Selon règles UNIVERS
    'RCI',           -- ID_TC_CG trouvé
    'NOUVEAU',       -- ID_TC_CIBLE trouvé
    '0',             -- '0' pour mercuriale
    1                -- 1=PRB_RC, 2=PRB_COLL
);

-- Ajouter aussi la variante FG_HM='1' si nécessaire
INSERT INTO PT0CE_TYPE_CLIENT_MAPPING (
    TYPE_CLIENT, UNIVERS, ID_TC_CG, ID_TC_CIBLE, FG_HM, PRB
) VALUES (
    'NOUVEAU TYPE HM',
    'ZOOM1',
    'RCI',
    'NOUVEAU',
    '1',  -- Hors mercuriale
    1
);

COMMIT;
  1. Relancer PT2QE Option 1

Mettre à jour les mappings TYPE_RESTAURANT

Fréquence recommandée : Avant chaque exécution PT2QE si nouveaux codes SFC.

Étapes :

  1. Identifier les LC_SFC_CIBLE non mappés :
SELECT DISTINCT
    c.LC_SFC_CIBLE,
    COUNT(DISTINCT c.ID_CLN) as NB_CLIENTS
FROM SYS_MD_CLIENT c
LEFT JOIN PT0CE_TYPE_RESTAURANT_MAPPING tr
    ON tr.LC_SFC_CIBLE = c.LC_SFC_CIBLE
WHERE c.LC_SFC_CIBLE IS NOT NULL
    AND tr.Type_Restaurant IS NULL
GROUP BY c.LC_SFC_CIBLE
ORDER BY NB_CLIENTS DESC;
  1. Ajouter les nouveaux mappings :
INSERT INTO PT0CE_TYPE_RESTAURANT_MAPPING (
    LC_SFC_CIBLE,
    Type_Restaurant
) VALUES (
    'NOUVEAU_SFC',
    'Nouveau Type Restaurant'
);

COMMIT;
  1. Relancer PT2QE Option 1

Valider les mappings avant exécution PT2QE

Script : validate_mappings.py

Utilisation :

python validate_mappings.py TARIFAIRE

Vérifications effectuées : - Existence des tables de mapping - Distribution FG_HM - Test de jointure avec conditions actuelles - Test de jointure TYPE_RESTAURANT - Présence des tables PT1CE_OPTIMAL

Sortie attendue :

=== VALIDATION DES MAPPINGS PT2QE ===

1. Vérification des tables de mapping...
   ✓ PT0CE_TYPE_CLIENT_MAPPING : 45 lignes
   ✓ PT0CE_TYPE_RESTAURANT_MAPPING : 120 lignes

2. Vérification des mappings FG_HM = '0'...
   Distribution FG_HM :
   - FG_HM = '0' : 25 lignes, 8 types client, 1 univers
   - FG_HM = '1' : 20 lignes, 7 types client, 1 univers

[...]

=== FIN DE LA VALIDATION ===

10. Index et performance

Index recommandés sur tables de mapping

PT0CE_TYPE_CLIENT_MAPPING :

CREATE INDEX IDX_PT0CE_TC_MAP 
ON PT0CE_TYPE_CLIENT_MAPPING (ID_TC_CG, ID_TC_CIBLE, UNIVERS, FG_HM)
COMPRESS;

PT0CE_TYPE_RESTAURANT_MAPPING :

CREATE INDEX IDX_PT0CE_TR_MAP 
ON PT0CE_TYPE_RESTAURANT_MAPPING (LC_SFC_CIBLE)
COMPRESS;

Index sur table enrichie

PT2QE_PRICE_OFFERS_ENRICHED :

-- Index composite pour matching corridors
CREATE INDEX IDX_PT2QE_ENRICHED_DIMS 
ON PT2QE_PRICE_OFFERS_ENRICHED (ID_ART, TYPE_CLIENT, TYPE_RESTAURANT, GEO)
COMPRESS;

-- Index sur client
CREATE INDEX IDX_PT2QE_ENRICHED_CLN 
ON PT2QE_PRICE_OFFERS_ENRICHED (ID_CLN)
COMPRESS;

📍 Comment vérifier les index :

-- Index sur une table
SELECT 
    index_name,
    column_name,
    column_position
FROM user_ind_columns
WHERE table_name = 'PT0CE_TYPE_CLIENT_MAPPING'
ORDER BY index_name, column_position;

11. Diagrammes de flux

Flux global enrichissement

┌─────────────────────────┐
│  SYS_TARIF_SIMULATION   │
│  (Offres de prix)       │
└────────────┬────────────┘
┌─────────────────────────┐
│  Extraction             │
│  extract_price_offers.py│
└────────────┬────────────┘
             ├──────────────────────────┐
             │                          │
             ▼                          ▼
┌──────────────────────┐   ┌──────────────────────┐
│  Historique FG_HM    │   │  Calcul UNIVERS      │
│  LAST_FG_HM          │   │  (Business Rules)    │
│  (4 derniers Q)      │   │                      │
└──────┬───────────────┘   └───────┬──────────────┘
       │                           │
       └───────────┬───────────────┘
┌──────────────────────────────────────┐
│  Jointure Mappings                   │
│  - PT0CE_TYPE_CLIENT_MAPPING         │
│  - PT0CE_TYPE_RESTAURANT_MAPPING     │
│  - SYS_MD_CLIENT (GEO)               │
└──────────────┬───────────────────────┘
┌──────────────────────────────────────┐
│  Filtre ZOOM1                        │
│  WHERE UNIVERS = 'ZOOM1'             │
│  AND TYPE_CLIENT IS NOT NULL         │
│  AND TYPE_RESTAURANT IS NOT NULL     │
└──────────────┬───────────────────────┘
┌──────────────────────────────────────┐
│  PT2QE_PRICE_OFFERS                  │
│  (Offres enrichies)                  │
└──────────────┬───────────────────────┘
┌──────────────────────────────────────┐
│  Matching Corridors                  │
│  corridor_matcher.py                 │
│  - Tentative MASTER (4D)             │
│  - Fallback NATIONAL (ID_ART)        │
└──────────────┬───────────────────────┘
┌──────────────────────────────────────┐
│  PT2QE_PRICE_OFFERS_ENRICHED         │
│  (Offres + Corridors)                │
└──────────────────────────────────────┘

Flux matching TYPE_CLIENT

┌─────────────┐
│  ID_TC_CG   │────┐
└─────────────┘    │
┌─────────────┐    │
│ ID_TC_CIBLE │────┼───┐
└─────────────┘    │   │
                   │   │
┌─────────────┐    │   │
│   UNIVERS   │────┼───┼───┐
│  (calculé)  │    │   │   │
└─────────────┘    │   │   │
                   │   │   │
┌─────────────┐    │   │   │
│   FG_HM     │────┼───┼───┼───┐
│ (historique)│    │   │   │   │
└─────────────┘    │   │   │   │
                   ▼   ▼   ▼   ▼
        ┌─────────────────────────────┐
        │ PT0CE_TYPE_CLIENT_MAPPING   │
        │ Clé composite (4 colonnes)  │
        └──────────────┬──────────────┘
                ┌─────────────┐
                │TYPE_CLIENT  │
                └─────────────┘

12. Checklist avant exécution PT2QE

À vérifier SYSTÉMATIQUEMENT :

  • [ ] PT1CE exécuté : Tables PT1CE_OPTIMAL_* présentes et remplies
  • [ ] Mappings TYPE_CLIENT : PT0CE_TYPE_CLIENT_MAPPING à jour
  • [ ] Mappings TYPE_RESTAURANT : PT0CE_TYPE_RESTAURANT_MAPPING à jour
  • [ ] Fichier capping : inputs/capping_type_client.csv présent
  • [ ] Calendrier fiscal : SYS_MD_CALENDRIER_SYSCO à jour (4 trimestres complets)
  • [ ] Espace disque : Suffisant pour tables PT2QE_*
  • [ ] Validation : python validate_mappings.py TARIFAIRE exécuté sans erreur

Commande de vérification rapide :

-- Checklist SQL complète
SELECT 'PT1CE ZOOM1' as CHECK_NAME, COUNT(*) as VALUE FROM PT1CE_OPTIMAL_ZOOM1 WHERE STATUS = 'OPTIMAL'
UNION ALL
SELECT 'MAPPING TYPE_CLIENT', COUNT(*) FROM PT0CE_TYPE_CLIENT_MAPPING
UNION ALL
SELECT 'MAPPING TYPE_RESTAURANT', COUNT(*) FROM PT0CE_TYPE_RESTAURANT_MAPPING
UNION ALL
SELECT 'CALENDRIER FISCAL', COUNT(DISTINCT ID_EXF || '_Q' || NO_TRF) FROM SYS_MD_CALENDRIER_SYSCO;

Seuils attendus :

Check Valeur minimum
PT1CE ZOOM1 > 10,000
MAPPING TYPE_CLIENT > 20
MAPPING TYPE_RESTAURANT > 50
CALENDRIER FISCAL > 8 trimestres

13. FAQ Technique

Q : Pourquoi FG_HM = 'X' devient '1' ?

R : Standardisation des valeurs. Dans SYS_FACTURE_LIGNE, le flag hors mercuriale peut être : - 'X' ou '1' → Hors mercuriale - NULL ou '0' → Mercuriale

PT2QE standardise en '0' ou '1' pour simplifier les jointures.


Q : Que se passe-t-il si je modifie un mapping pendant que PT2QE tourne ?

R : Aucun impact. PT2QE lit les mappings au moment de l'extraction (Option 1). Les modifications ne seront prises en compte qu'à la prochaine exécution complète.


Q : Pourquoi UNIVERS est calculé AVANT la jointure TYPE_CLIENT ?

R : Car UNIVERS est une dimension nécessaire pour la jointure. Le mapping TYPE_CLIENT dépend de l'UNIVERS :

UNIVERS (calculé) + ID_TC_CG + ID_TC_CIBLE + FG_HM → TYPE_CLIENT

Sans UNIVERS, la jointure échoue.


Q : Peut-on avoir plusieurs TYPE_CLIENT pour une même combinaison ID_TC_CG/ID_TC_CIBLE ?

R : Oui, si FG_HM diffère :

RCI + PINDEP + FG_HM='0' → "RCI PI GI"
RCI + PINDEP + FG_HM='1' → "RCI PI GI HM"

Mais pour un UNIVERS donné, la clé (UNIVERS, ID_TC_CG, ID_TC_CIBLE, FG_HM) doit être unique.


Q : Que signifie MATCH_TYPE = 'NATIONAL' ?

R : L'offre n'a pas trouvé de corridor MASTER (spécifique à ses dimensions), donc PT2QE utilise un corridor agrégé au niveau TYPE_CLIENT='NATIONAL'.

Impact : Recommandations moins précises (corridor moyen).


Q : Comment forcer un TYPE_CLIENT spécifique pour un client ?

R : Impossible directement. Le TYPE_CLIENT provient du mapping sur (UNIVERS, ID_TC_CG, ID_TC_CIBLE, FG_HM).

Solutions : 1. Modifier le mapping dans PT0CE_TYPE_CLIENT_MAPPING 2. Corriger ID_TC_CG ou ID_TC_CIBLE dans SYS_MD_CLIENT (côté SAP)


Q : Les offres ZOOM2/ZOOM3 sont-elles perdues ?

R : Non. Elles sont extraites mais exclues du calcul PT2QE actuel.

Pour les inclure : 1. Retirer le filtre WHERE UNIVERS = 'ZOOM1' dans extract_price_offers.py 2. Adapter le matching corridors pour utiliser PT1CE_OPTIMAL_ZOOM2 et PT1CE_OPTIMAL_ZOOM3


14. Dépannage rapide

Symptôme Cause probable Solution
TYPE_CLIENT IS NULL Mapping manquant ou FG_HM NULL Ajouter mapping ou vérifier historique
MATCH_TYPE = 'NO_MATCH' Article sans corridor PT1CE Exécuter PT1CE ou attendre plus de transactions
UNIVERS = 'HORS PERIMETRE' Règles UNIVERS ne couvrent pas ce cas Ajouter règle dans extract_price_offers.py
GEO IS NULL Client sans zone géographique SAP Corriger LC_ZDV_GRV dans SYS_MD_CLIENT
FG_HM toujours = '0' Client uniquement mercuriale Attendre transactions HM ou vérifier historique

15. Commandes utiles

Réinitialiser les tables PT2QE

-- ATTENTION : Supprime toutes les données PT2QE
BEGIN
    FOR t IN (SELECT table_name FROM user_tables WHERE table_name LIKE 'PT2QE_%') LOOP
        EXECUTE IMMEDIATE 'DROP TABLE ' || t.table_name || ' PURGE';
    END LOOP;
END;
/

Exporter les mappings

# TYPE_CLIENT
sqlplus user/pass@TARIFAIRE <<EOF
SET COLSEP ';'
SET PAGESIZE 0
SET TRIMSPOOL ON
SET HEADSEP OFF
SET LINESIZE 300
SPOOL mappings_type_client.csv
SELECT TYPE_CLIENT||';'||UNIVERS||';'||ID_TC_CG||';'||ID_TC_CIBLE||';'||FG_HM||';'||PRB
FROM PT0CE_TYPE_CLIENT_MAPPING
ORDER BY UNIVERS, TYPE_CLIENT;
SPOOL OFF
EXIT;
EOF

Comparer 2 runs PT2QE

-- Différences de TYPE_CLIENT entre 2 runs
SELECT 
    r1.ID_CLN,
    r1.ID_ART,
    r1.TYPE_CLIENT as TYPE_CLIENT_RUN1,
    r2.TYPE_CLIENT as TYPE_CLIENT_RUN2
FROM PT2QE_PRICE_OFFERS_RUN1 r1
JOIN PT2QE_PRICE_OFFERS_RUN2 r2
    ON r1.ID_CLN = r2.ID_CLN
    AND r1.ID_ART = r2.ID_ART
WHERE r1.TYPE_CLIENT <> r2.TYPE_CLIENT;

Fin du document