Aller au contenu

Export SAP - PT1CE

Table des matières

  1. Vue d'ensemble de l'export
  2. Structure des extracts
  3. Format Excel SAP
  4. Traitement MASTER vs NATIONAL
  5. Gestion de la volumétrie
  6. Exemples de sortie

Vue d'ensemble de l'export

Objectif

L'export SAP transforme les corridors optimaux en fichiers Excel formatés pour l'import dans SAP, avec calcul automatique des taux de remise.

Architecture de l'export

graph TD
    A[PT1CE_OPTIMAL_ZOOM1/2/3] --> B{4 extracts}

    B --> C[NATIONAL PRB01]
    B --> D[NATIONAL PRB02]
    B --> E[MASTER PRB01]
    B --> F[MASTER PRB02]

    E --> G[PT0CE_DIMENSION_MAPPING]
    F --> G

    C --> H[Excel sans codes]
    D --> H
    E --> I[Excel avec codes]
    F --> I

    style C fill:#ffcc99
    style D fill:#ffcc99
    style E fill:#99ccff
    style F fill:#99ccff

Points clés

  • 4 extracts séparés : Par type de cube × type de PRB
  • Codes sources : Uniquement pour les cubes MASTER
  • Format fixe : En-têtes ligne 18, colonnes SAP
  • Division automatique : Si > 400k lignes

Structure des extracts

Extract 1 : NATIONAL avec PRB_TO_USE = 1

Caractéristiques :
- Corridors NATIONAL uniquement
- Utilise PRB_RC pour les calculs
- Type tarif = '01'
- Codes sources vides

Requête SQL :

SELECT 
    c.*,
    NULL as ID_TC_CIBLE,
    NULL as ID_SFC_CIBLE,
    NULL as ID_RGC_GRV_SAP
FROM CORRIDORS c
WHERE c.CUBE_TYPE = 'NATIONAL'
  AND c.PRB_TO_USE = 1

Extract 2 : NATIONAL avec PRB_TO_USE = 2

Caractéristiques :
- Corridors NATIONAL uniquement
- Utilise PRB_COLL pour les calculs
- Type tarif = '02'
- Codes sources vides

Extract 3 : MASTER avec PRB_TO_USE = 1

Caractéristiques :
- Corridors MASTER uniquement
- Utilise PRB_RC pour les calculs
- Type tarif = '01'
- Codes sources depuis PT0CE_DIMENSION_MAPPING

Requête SQL :

SELECT 
    c.*,
    m.ID_TC_CIBLE,
    m.ID_SFC_CIBLE,
    m.ID_RGC_GRV_SAP
FROM CORRIDORS c
INNER JOIN PT0CE_DIMENSION_MAPPING m
    ON c.ID_ART = m.ID_ART  
    AND c.CATEGORY = m.UNIVERS
    AND c.TYPE_CLIENT = m.TYPE_CLIENT
    AND c.TYPE_RESTAURANT = m.TYPE_RESTAURANT
    AND NVL(c.GEO, 'NULL') = NVL(m.GEO, 'NULL')
WHERE c.CUBE_TYPE = 'MASTER'
  AND c.PRB_TO_USE = 1

Extract 4 : MASTER avec PRB_TO_USE = 2

Caractéristiques :
- Corridors MASTER uniquement
- Utilise PRB_COLL pour les calculs
- Type tarif = '02'
- Codes sources depuis PT0CE_DIMENSION_MAPPING

Format Excel SAP

Structure du fichier

Lignes 1-17   : Vides (réservées SAP)
Ligne 18      : En-têtes
Lignes 19+    : Données

Colonnes et mapping

Colonne Nom SAP Contenu PT1CE Exemple
A (vide) Vide
B code_sequence 526 526
C paliers Code tarif SAP ZRPL
D code_sequence_copy 526 526
E orga 1000 1000
F canal 10 10
G Type tarif PRB_TO_USE formaté 01
H-L (vides) Vides
M code_typo ID_TC_CIBLE ou vide PINDEP
N code_gira ID_SFC_CIBLE ou vide REST_T
O-R (vides) Vides
S code_region ID_RGC_GRV_SAP ou vide 75
T (vide) Vide
U Code_Article ID_ART 075130
V Montant Taux de remise 0.15
W-Y (vides) Vides
Z debut Date début 01.10.2025
AA fin Date fin 31.12.9999

Mapping des paliers

Code SAP Borne PT1CE Description
ZRPL NEW_BORNE_PL6_PLX Palier libre (le plus bas)
ZP05 NEW_BORNE_PL5_PL6 Palier 5
ZP04 NEW_BORNE_PL4_PL5 Palier 4
ZP03 NEW_BORNE_PL3_PL4 Palier 3
ZP02 NEW_BORNE_PL2_PL3 Palier 2
ZPP1 NEW_BORNE_PL1_PL2 Palier 1 (le plus haut)

Calcul du montant (taux de remise)

# Formule
taux_remise = (PRB - Borne) / PRB

# Exemple
PRB = 20.00
Borne = 17.00
Taux = (20.00 - 17.00) / 20.00 = 0.15 = 15%

Traitement MASTER vs NATIONAL

Différences principales

graph LR
    subgraph "Cube MASTER"
        A1[ID_ART: 075130]
        A2[TYPE_CLIENT: RCI PI GI]
        A3[TYPE_RESTAURANT: REST. TRADI]
        A4[GEO: IDF]
    end

    subgraph "Mapping PT0CE"
        B1[ID_TC_CIBLE: PINDEP]
        B2[ID_SFC_CIBLE: REST_T]
        B3[ID_RGC_GRV_SAP: 75]
    end

    subgraph "Export MASTER"
        C1[code_typo: PINDEP]
        C2[code_gira: REST_T]
        C3[code_region: 75]
    end

    A1 --> B1
    A2 --> B1
    A3 --> B2
    A4 --> B3

    B1 --> C1
    B2 --> C2
    B3 --> C3
graph LR
    subgraph "Cube NATIONAL"
        D1[ID_ART: 075130]
        D2[Dimensions: NATIONAL]
    end

    subgraph "Export NATIONAL"
        E1[code_typo: vide]
        E2[code_gira: vide]
        E3[code_region: vide]
    end

    D1 --> E1
    D2 --> E1
    D2 --> E2
    D2 --> E3

Gestion de PT0CE_DIMENSION_MAPPING

Si la table existe :
- Export complet des 4 extracts
- Codes sources remplis pour MASTER
- Codes vides pour NATIONAL

Si la table n'existe pas :
- Export des corridors NATIONAL uniquement
- Warning dans les logs
- Cubes MASTER ignorés

Exemple de ligne exportée

MASTER avec codes

526 | ZRPL | 526 | 1000 | 10 | 01 | | | | | | | PINDEP | REST_T | | | | | 75 | | 075130 | 0.15 | | | | 01.10.2025 | 31.12.9999

NATIONAL sans codes

526 | ZRPL | 526 | 1000 | 10 | 01 | | | | | | | | | | | | | | | 075130 | 0.15 | | | | 01.10.2025 | 31.12.9999

Gestion de la volumétrie

Problématique

Un corridor génère 6 lignes (une par palier) :
- 100k corridors = 600k lignes
- Limite Excel SAP = 400k lignes

Solution : Division automatique

def split_excel_files(data, max_rows=400000):
    total_rows = len(data)
    num_files = (total_rows - 1) // max_rows + 1

    for file_idx in range(num_files):
        start_idx = file_idx * max_rows
        end_idx = min((file_idx + 1) * max_rows, total_rows)

        chunk_data = data.iloc[start_idx:end_idx]
        filename = f'{extract_name}_part{file_idx + 1:02d}.xlsx'
        create_sap_excel(chunk_data, filename)

Structure des dossiers

outputs/export_sap_YYYYMMDD_HHMMSS/sap_export/
├── national_prb01/
│   ├── national_prb01_part01.xlsx  (400k lignes)
│   └── national_prb01_part02.xlsx  (150k lignes)
├── national_prb02/
│   └── national_prb02_part01.xlsx  (380k lignes)
├── master_prb01/
│   ├── master_prb01_part01.xlsx    (400k lignes)
│   ├── master_prb01_part02.xlsx    (400k lignes)
│   └── master_prb01_part03.xlsx    (200k lignes)
└── master_prb02/
    └── master_prb02_part01.xlsx     (250k lignes)

Statistiques affichées

Export 1/4 : NATIONAL - PRB_TO_USE = 1...
  → 125,432 corridors trouvés
  → 752,592 lignes SAP générées
  → Fichier créé : national_prb01_part01.xlsx
  → Fichier créé : national_prb01_part02.xlsx

Exemples de sortie

Exemple 1 : Corridor MASTER complet

Données du corridor :

ID_ART: 075130
TYPE_CLIENT: RCI PI GI
TYPE_RESTAURANT: REST. TRADI
GEO: IDF
PRB_TO_USE: 1
NEW_PRB_RC: 15.820
NEW_BORNE_PL1_PL2: 14.000
NEW_BORNE_PL2_PL3: 13.500
NEW_BORNE_PL3_PL4: 12.800
NEW_BORNE_PL4_PL5: 12.000
NEW_BORNE_PL5_PL6: 11.200
NEW_BORNE_PL6_PLX: 10.500

Codes depuis mapping :

ID_TC_CIBLE: PINDEP
ID_SFC_CIBLE: REST_T
ID_RGC_GRV_SAP: 75

Lignes Excel générées :

526 | ZPP1 | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.11 | ... | 01.10.2025 | 31.12.9999
526 | ZP02 | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.15 | ... | 01.10.2025 | 31.12.9999
526 | ZP03 | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.19 | ... | 01.10.2025 | 31.12.9999
526 | ZP04 | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.24 | ... | 01.10.2025 | 31.12.9999
526 | ZP05 | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.29 | ... | 01.10.2025 | 31.12.9999
526 | ZRPL | ... | 01 | ... | PINDEP | REST_T | ... | 75 | ... | 075130 | 0.34 | ... | 01.10.2025 | 31.12.9999

Exemple 2 : Corridor NATIONAL

Données du corridor :

ID_ART: 075150
CUBE_TYPE: NATIONAL
PRB_TO_USE: 2
NEW_PRB_COLL: 4.250
NEW_BORNE_PL1_PL2: 3.900

Ligne Excel générée :

526 | ZPP1 | ... | 02 | ... | | | ... | | ... | 075150 | 0.08 | ... | 01.10.2025 | 31.12.9999

Note : Codes typo/gira/region vides pour NATIONAL

Exemple 3 : Gestion des bornes NULL

Corridor avec bornes partielles :

NEW_BORNE_PL1_PL2: NULL
NEW_BORNE_PL2_PL3: 13.500
NEW_BORNE_PL3_PL4: 12.800

Export :
- Ligne ZPP1 : Non générée (borne NULL)
- Ligne ZP02 : Générée normalement
- Ligne ZP03 : Générée normalement

Validation du format

def validate_sap_format(excel_file):
    # Vérifier en-têtes ligne 18
    header_row = ws[18]
    expected_headers = ['', 'code_sequence', 'paliers', ...]

    # Vérifier Type tarif (01 ou 02)
    for row in data_rows:
        type_tarif = row['Type tarif']
        if type_tarif not in ['01', '02']:
            raise ValueError(f"Type tarif invalide: {type_tarif}")

    # Vérifier format dates
    date_pattern = r'^\d{2}\.\d{2}\.\d{4}$'
    if not re.match(date_pattern, row['debut']):
        raise ValueError("Format date invalide")