Aller au contenu

Diagrammes Step 05 - Building Baseline Effects

Vue d'ensemble du processus

graph TB
    Start([main]) --> VE[main_volume_effects]
    VE --> QC[main_quality_check]

    subgraph "Calcul des effets de volume"
        V1[Uplift Volume]
        V2[Cannibalization Volume]
        V3[Forward Buying<br/>Galbani uniquement]
        V4[Halo & Pantry Loading<br/>Initialisation]

        V1 --> V2 --> V3 --> V4
    end

    subgraph "Quality Check"
        Q1[Stock-up effect analysis]
        Q2[Base 100 normalization]
        Q3[Export CSV results]

        Q1 --> Q2 --> Q3
    end

    VE --> V1
    V4 --> QC
    QC --> Q1
    Q3 --> End([Fin])

Dispatcher selon business unit

flowchart TD
    Start[apply_volume_effects_computation]

    Check1{Sell_out_availability?}
    Start --> Check1

    Check1 -->|1| SellOut[compute_volume_effects_with_sell_out]
    Check1 -->|0| Check2{Business Unit?}

    Check2 -->|italy_galbani| Galbani[compute_volume_effects_italy_galbani]
    Check2 -->|italy_parmalat| Parmalat[compute_volume_effects_italy_parmalat]
    Check2 -->|autres| Skip[Log: Unknown BU]

    style Galbani fill:#e3f2fd
    style Parmalat fill:#fff3e0
    style SellOut fill:#e8f5e9

Calcul Uplift Volume

stateDiagram-v2
    [*] --> Check: Pour chaque ligne

    Check --> PromoCheck: Flag_Promo = 1?

    PromoCheck --> BaselineCheck: OUI
    PromoCheck --> SetNaN: NON

    BaselineCheck --> HasBaseline: Baseline existe?

    HasBaseline --> CalcUplift: OUI
    HasBaseline --> SetNaN: NON

    CalcUplift --> Formula: Volume - Baseline

    Formula --> CheckNegative: Uplift < 0?

    CheckNegative --> SetNaN2: OUI
    CheckNegative --> KeepValue: NON

    SetNaN --> Result: Uplift = NaN
    SetNaN2 --> Result
    KeepValue --> Result: Uplift = valeur

    Result --> [*]

Calcul Cannibalization Volume

flowchart LR
    subgraph "Conditions"
        C1(Flag_qualified_week = 1)
        C2(Flag_Outliers = 0)
        C3{Conditions remplies?}

        C1 --> C3
        C2 --> C3
    end

    subgraph "Calcul"
        CALC(Volume - Baseline)
        MIN("min(résultat, 0)")

        CALC --> MIN
    end

    C3 -->|OUI| CALC
    C3 -->|NON| NAN(Cannib = NaN)
    MIN --> RESULT(Cannib_Volume)

    style MIN fill:#ffebee

Forward Buying Galbani - Vue d'ensemble

graph TB
    subgraph "1. Delta Promo Intensity"
        D1[Sell-in intensity]
        D2[Sell-out intensity<br/>Channel spécifique]
        D3[Delta = SI - SO]
        D4[Si < 0 → 0]

        D1 --> D3
        D2 --> D3
        D3 --> D4
    end

    subgraph "2. Forward Buying Factors"
        F1[Classification par<br/>sous-catégorie]
        F2[Risk mapping<br/>low/mid/high]
        F3[Factors<br/>0.2/0.4/0.6]

        F1 --> F2 --> F3
    end

    subgraph "3. Calcul final"
        C1[Delta_adjusted =<br/>Delta × Factor]
    end

    D4 --> C1
    F3 --> C1

Forward Buying Galbani - Promo Intensities

sequenceDiagram
    participant Main as compute_volume_effects
    participant Fetch as fetch_promo_intensities
    participant DB as Database

    Main->>Fetch: Request promo intensities

    Note over Fetch: Sell-in aggregation
    Fetch->>DB: SELECT New_category, EAN, Year,<br/>SUM(volumes) FROM step_3_01_after_scoping<br/>GROUP BY ...
    DB-->>Fetch: Sell-in data

    Note over Fetch: Sell-out aggregation
    Fetch->>DB: SELECT EAN, Year, SUM(volumes)<br/>FROM sell_out_base<br/>WHERE Channel = 'IS+LSP (100-399mq) (7002)'
    DB-->>Fetch: Sell-out data

    Fetch->>Fetch: Calculate intensities
    Fetch->>Fetch: Merge on EAN, Year
    Fetch->>Fetch: Delta = SI - SO

    alt Missing Delta - Case 1
        Fetch->>Fetch: Calculate category average<br/>for matched EANs
        Fetch->>Fetch: Fill missing with avg
    else Missing Delta - Case 2
        Fetch->>DB: Get SUB_CAT mapping
        Fetch->>Fetch: Calculate at SUB_CAT level
        Fetch->>Fetch: Average by New_category
    end

    Fetch-->>Main: DataFrame with Delta values

Forward Buying Factors Mapping

graph LR
    subgraph "Risk Classification"
        R1[Forward_buying_classification<br/>SUB_CAT_PROD_LIV2<br/>M7_SUB_CAT_PROD<br/>Forward_buying_risk]
    end

    subgraph "Factor Mapping"
        M1[low → 0.2]
        M2[medium → 0.4]
        M3[high → 0.6]
    end

    subgraph "EAN Assignment"
        E1[sell_in_base<br/>EAN, EAN_desc<br/>Sub_Category_1/2]
        E2[Merge on<br/>sub-categories]
        E3[EAN → Factor]
    end

    R1 --> M1
    R1 --> M2
    R1 --> M3

    E1 --> E2
    M1 --> E2
    M2 --> E2
    M3 --> E2
    E2 --> E3

Parmalat - Initialisation

stateDiagram-v2
    [*] --> CalcUplift: compute_volume_effects_italy_parmalat

    CalcUplift --> InitHalo: Calculer Uplift (standard)

    InitHalo --> SetNaN: Halo_Volume = NaN

    SetNaN --> InitPantry: Pantry_Loading_Volume = NaN

    InitPantry --> CalcCannib: Calculer Cannibalization

    CalcCannib --> Save: Sauvegarder table

    Save --> [*]: step_4_01_model_with_effects_baseline

    note right of InitHalo
        Halo et Pantry Loading
        seront calculés dans
        Step 6.01 après
        promotion code carryover
    end note

Sell-out - Halo & Pantry Loading

flowchart TD
    Param{"Halo_and_pantry_loading<br/>computation = 1?"}

    Param -->|OUI| Calc
    Param -->|NON| Init("Halo = NaN<br/>Pantry = NaN")

    subgraph Calc[Calcul effectif]
        C1(Flag_Buying_period_post_promo = 1)
        C2(Flag_Outliers = 0)
        C3{Conditions OK?}

        C1 --> C3
        C2 --> C3

        C3 -->|OUI| Delta("Δ = Volume - Baseline")
        C3 -->|NON| SetNaN(NaN)

        Delta --> Halo("Halo = max(Δ, 0)")
        Delta --> Pantry("Pantry = min(Δ, 0)")
    end

Quality Check - Stock-up Effect

sequenceDiagram
    participant QC as quality_check_stock_up_effect
    participant DB as Database
    participant Calc as Calculator

    QC->>DB: Load step_3_02_model_data_baseline
    DB-->>QC: DataFrame

    QC->>QC: Filter years_in_scope

    loop Pour chaque groupe (Brand×Category×Year×EAN×Retailer)
        QC->>Calc: Calculate averages

        Note over Calc: Base: Flag_qualified_week=1
        Calc->>Calc: base_avg = mean(volumes)

        Note over Calc: Promo: Flag_Promo=1
        Calc->>Calc: promo_avg = mean(volumes)

        Note over Calc: Post-promo weeks
        Calc->>Calc: week+1 avg after promo
        Calc->>Calc: week+2 avg after promo
        Calc->>Calc: week+3 avg after promo

        Calc->>Calc: Normalize to base 100
        Calc-->>QC: Results
    end

    QC->>QC: Aggregate by Brand×Category×Year
    QC->>QC: Export to CSV

Structure des résultats Quality Check

graph TD
    subgraph "Données calculées"
        D1("No_promo = 100<br/>Base de référence")
        D2("Promo = Index pendant promo")
        D3("Week_plus_one = Index S+1")
        D4("Week_plus_two = Index S+2")
        D5("Week_plus_three = Index S+3")
    end

    subgraph "Agrégation finale"
        A1("GROUP BY<br/>Year, Brand, Category")
        A2("MEAN de tous les index")
    end

    subgraph "Export CSV"
        E1("qc1_stock_up_effect_{bu}_{country}.csv")
        E2("Séparateur: ';'")
    end

    D1 --> A1
    D2 --> A1
    D3 --> A1
    D4 --> A1
    D5 --> A1

    A1 --> A2 --> E1

Flow complet avec types de données

graph LR
    subgraph "Input"
        I1[(step_3_02_model_data_baseline)]
        I2[promo_config.json]
    end

    subgraph "Processing"
        P1[Type casting<br/>Year: int<br/>Volumes: float<br/>Flags: float]
        P2[Calculs vectorisés]
        P3[Gestion NaN]
    end

    subgraph "Output"
        O1[(step_4_01_model_with_effects_baseline)]
        O2[Quality checks/<br/>qc1_stock_up_effect_*.csv]
    end

    I1 --> P1
    I2 --> P1
    P1 --> P2
    P2 --> P3
    P3 --> O1
    P3 --> O2

    style O1 fill:#90EE90
    style O2 fill:#fff9c4

Points clés par business unit

mindmap
  root((Step 05<br/>Baseline<br/>Effects))
    Galbani
      Forward Buying
        Delta promo intensity
        Channel IS+LSP
        Factors par sous-cat
        Delta_adjusted final
      Uplift/Cannib
        Calculs standards
        Neutralisation négatifs
      Pas de Halo/Pantry
        Sans sell-out
    Parmalat
      Pas de Forward Buying
        Calculé en Step 6.01
      Uplift/Cannib
        Calculs standards
      Halo/Pantry = NaN
        Besoin promo codes
        Step 6.01
    Sell-out
      Paramètre config
        Halo_and_pantry_loading
      Si activé
        Post-promo effects
        Max/Min avec baseline
      Cannibalization
        Standard

Gestion des erreurs et cas limites

flowchart TD
    subgraph "Tables manquantes"
        T1[table_exists check]
        T2[Skip avec log]
        T1 -->|False| T2
    end

    subgraph "Colonnes adaptatives"
        C1{Sales_Volumes<br/>existe?}
        C2[Utiliser Sales_Volumes]
        C3[Utiliser Week_total_volume]
        C1 -->|OUI| C2
        C1 -->|NON| C3
    end

    subgraph "Valeurs manquantes"
        V1[Delta missing]
        V2[Category average]
        V3[Sub-category average]
        V1 --> V2
        V2 -->|Still missing| V3
    end

    subgraph "Protection calculs"
        P1[Division par zéro]
        P2[Valeurs infinies]
        P3[Return NaN]
        P1 --> P3
        P2 --> P3
    end