Files
vending_data_intelligence_r…/PLAN_CONSOLIDARE_RAPOARTE.md
Marius Mutu a2ad4c7ed2 Add implementation plan for report consolidation
Plan includes:
- Fix CONCENTRARE_RISC_YOY bug (CROSS JOIN issue)
- Consolidate 4 groups of sheets/pages:
  1. Executive Summary (3→1)
  2. Revenue Indicators (2→1)
  3. Client Portfolio + Risk (3→1)
  4. Financial Dashboard (5→1)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 16:30:12 +02:00

10 KiB

Plan: Consolidare Rapoarte PDF și Excel

Obiectiv

Consolidarea paginilor din raportul PDF și sheet-urilor din raportul Excel pentru o vedere de ansamblu rapidă, eliminând redundanțele și agregând datele conexe.


Fișiere de Modificat

Fișier Modificări
queries.py Fix bug CONCENTRARE_RISC_YOY (liniile 2035-2133)
report_generator.py Adăugare 4 metode noi pentru consolidare
main.py Actualizare sheet_order, legends, și fluxul de generare

Task 1: Fix Bug CONCENTRARE_RISK_YOY (queries.py)

Problema: Query-ul returnează "Nu există date" când metrics_anterior este gol (CROSS JOIN cu set gol = 0 rânduri). Aplicația verifică if df.empty și afișează "Nu există date".

Locație: queries.py liniile 2035-2133

Cauza Root:

  • vanzari_anterior poate fi gol (0 vânzări în perioada 12-24 luni)
  • ranked_anterior va fi gol
  • metrics_anterior va avea 1 rând dar cu toate valorile NULL
  • La CROSS JOIN cu metrics_curent, rezultatul are NULLs
  • Dar problema reală: când ranked_anterior este gol, SUM() în Oracle returnează NULL, nu 0

Soluție Detaliată:

  1. Redenumește metrics_anterior în metrics_anterior_raw
  2. Adaugă CTE metrics_anterior cu fallback la 0:
metrics_anterior_raw AS (
    SELECT
        SUM(vanzari) AS total,
        SUM(CASE WHEN rn <= 1 THEN vanzari ELSE 0 END) AS top1,
        SUM(CASE WHEN rn <= 5 THEN vanzari ELSE 0 END) AS top5,
        SUM(CASE WHEN rn <= 10 THEN vanzari ELSE 0 END) AS top10
    FROM ranked_anterior
),
metrics_anterior AS (
    SELECT
        NVL(total, 0) AS total,
        NVL(top1, 0) AS top1,
        NVL(top5, 0) AS top5,
        NVL(top10, 0) AS top10
    FROM metrics_anterior_raw
)
  1. Modifică calculul în combined să trateze cazul când total anterior = 0:
ROUND(ma.top1 * 100.0 / NULLIF(ma.total, 0), 2) AS pct_anterior_1,
-- devine:
CASE WHEN ma.total = 0 THEN NULL ELSE ROUND(ma.top1 * 100.0 / ma.total, 2) END AS pct_anterior_1,
  1. Adaugă coloana HAS_ANTERIOR pentru a indica dacă există date YoY

Task 2: Excel - Metodă Consolidare Sheet-uri Multiple (report_generator.py)

Adaugă metodă nouă: add_consolidated_sheet()

Semnătură:

def add_consolidated_sheet(
    self,
    name: str,
    sections: List[Dict],  # [{'title': str, 'df': DataFrame, 'description': str, 'legend': dict}]
    sheet_title: str,
    sheet_description: str
) -> None

Comportament:

  • Creează un singur sheet cu multiple secțiuni separate vizual
  • Fiecare secțiune are: titlu bold, descriere, tabel date, legendă
  • Spațiere de 3 rânduri între secțiuni
  • Aplică formatare condiționată standard (culori status/trend)

Task 3: PDF - Metodă Pagină Consolidată (report_generator.py)

Adaugă metodă nouă: add_consolidated_page()

Semnătură:

def add_consolidated_page(
    self,
    page_title: str,
    sections: List[Dict]  # [{'title': str, 'df': DataFrame, 'columns': list, 'max_rows': int}]
) -> None

Comportament:

  • Adaugă titlu pagină
  • Iterează prin secțiuni, adăugând sub-titluri și tabele
  • Gestionează page breaks când depășește spațiul

Task 4: Consolidare 1 - Vedere Executivă (main.py + report_generator.py)

Combină: sumar_executiv + sumar_executiv_yoy + recomandari

Excel:

  • Sheet nou: "Vedere Ansamblu"
  • Structură:
    [Titlu: Vedere Ansamblu Executivă]
    
    === KPIs cu Comparație YoY ===
    | Indicator | Valoare Curentă | UM | Valoare Anterioară | Variație % | Trend |
    
    === Recomandări Prioritare ===
    | Status | Categorie | Indicator | Valoare | Recomandare |
    
    [Legendă completă pentru toate coloanele]
    

PDF:

  • Pagină 2: Tot conținutul într-o singură pagină
  • KPIs + YoY side-by-side în partea de sus
  • Recomandări (toate) în partea de jos

Implementare:

  1. În main.py: Creează DataFrame combinat din sumar_executiv JOIN sumar_executiv_yoy pe INDICATOR
  2. Apelează noua metodă add_consolidated_sheet() pentru Excel
  3. Apelează noua metodă add_consolidated_page() pentru PDF

Task 5: Consolidare 2 - Indicatori Agregați Venituri (main.py)

Combină: indicatori_agregati_venituri + indicatori_agregati_venituri_yoy

Excel:

  • Sheet nou: "Indicatori Venituri"
  • Structură:
    | Linie Business | Vânzări Curente | Marjă % | Vânzări Anterioare | Variație % | Trend |
    

PDF:

  • Pagină 3: Un singur tabel consolidat

Implementare:

  1. Merge DataFrames pe LINIE_BUSINESS
  2. Elimină coloane duplicate
  3. Redenumește coloane pentru claritate

Task 6: Consolidare 3 - Portofoliu Clienți + Concentrare Risc (main.py)

Combină: portofoliu_clienti + concentrare_risc + concentrare_risc_yoy

Excel:

  • Sheet nou: "Clienți și Risc"
  • Structură:
    === Portofoliu Clienți ===
    | Categorie | Valoare | Explicație |
    
    === Concentrare Risc (Curent vs Anterior) ===
    | Indicator | % Curent | Status | % Anterior | Variație | Trend |
    
    [Legende pentru ambele secțiuni]
    

PDF:

  • Pagină 4: Două tabele pe aceeași pagină

Implementare:

  1. Merge concentrare_risc cu concentrare_risc_yoy pe INDICATOR
  2. Folosește add_consolidated_sheet() cu 2 secțiuni

Task 7: Consolidare 4 - Tablou Financiar (main.py)

Combină: indicatori_generali + indicatori_lichiditate + clasificare_datorii + grad_acoperire_datorii + proiectie_lichiditate

Excel:

  • Sheet nou: "Tablou Financiar"
  • Structură:
    === Indicatori Generali (Solvabilitate) ===
    [tabel + legendă]
    
    === Indicatori Lichiditate ===
    [tabel + legendă]
    
    === Clasificare Datorii pe Termene ===
    [tabel + legendă]
    
    === Grad Acoperire Datorii ===
    [tabel + legendă]
    
    === Proiecție Lichiditate 30/60/90 zile ===
    [tabel + legendă]
    

PDF:

  • Pagină 5: Toate cele 5 secțiuni (compact, fără grafice)

Implementare:

  1. Folosește add_consolidated_sheet() cu 5 secțiuni
  2. Păstrează interpretările și recomandările din fiecare secțiune

Task 8: Actualizare sheet_order (main.py)

Modifică sheet_order pentru a reflecta noua structură:

sheet_order = [
    # CONSOLIDAT - Vedere Ansamblu
    'vedere_ansamblu',  # NOU - înlocuiește sumar_executiv, sumar_executiv_yoy, recomandari

    # CONSOLIDAT - Indicatori Venituri
    'indicatori_venituri',  # NOU - înlocuiește indicatori_agregati_venituri, indicatori_agregati_venituri_yoy

    # CONSOLIDAT - Clienți și Risc
    'clienti_risc',  # NOU - înlocuiește portofoliu_clienti, concentrare_risc, concentrare_risc_yoy

    # CONSOLIDAT - Tablou Financiar
    'tablou_financiar',  # NOU - înlocuiește cele 5 sheet-uri financiare

    # DETALII (neschimbat)
    'sezonalitate_lunara',
    'vanzari_sub_cost',
    'clienti_marja_mica',
    # ... restul sheet-urilor de detaliu ...
]

Elimină din sheet_order:

  • sumar_executiv, sumar_executiv_yoy, recomandari
  • indicatori_agregati_venituri, indicatori_agregati_venituri_yoy
  • portofoliu_clienti, concentrare_risc, concentrare_risc_yoy
  • indicatori_generali, indicatori_lichiditate, clasificare_datorii, grad_acoperire_datorii, proiectie_lichiditate

Task 9: Actualizare legends (main.py)

Adaugă legendele pentru sheet-urile consolidate:

legends['vedere_ansamblu'] = {
    'INDICATOR': 'Denumirea indicatorului de business',
    'VALOARE_CURENTA': 'Valoare în perioada curentă (ultimele 12 luni)',
    'UM': 'Unitate de măsură',
    'VALOARE_ANTERIOARA': 'Valoare în perioada anterioară (12-24 luni)',
    'VARIATIE_PROCENT': 'Variație procentuală YoY',
    'TREND': 'CREȘTERE/SCĂDERE/STABIL',
    # Pentru recomandări:
    'STATUS': 'OK = bine, ATENȚIE = necesită atenție, ALERTĂ = acțiune urgentă',
    'CATEGORIE': 'Domeniu: Marja, Clienți, Stoc, Financiar',
    'RECOMANDARE': 'Acțiune sugerată'
}
# ... similar pentru celelalte 3 sheet-uri consolidate

Task 10: Actualizare Flux Generare PDF (main.py)

Modifică secțiunea de generare PDF (~liniile 495-612):

# Pagina 1: Titlu
pdf.add_title_page(report_date)

# Pagina 2: Vedere Executivă (CONSOLIDAT)
pdf.add_consolidated_page('Vedere Executivă', [
    {'title': 'KPIs cu Comparație YoY', 'df': combined_kpi_df, 'columns': [...], 'max_rows': 20},
    {'title': 'Recomandări', 'df': results['recomandari'], 'columns': [...], 'max_rows': 15}
])

# Pagina 3: Indicatori Venituri (CONSOLIDAT)
pdf.add_table_section('Indicatori Venituri', combined_venituri_df, [...])

# Pagina 4: Clienți și Risc (CONSOLIDAT)
pdf.add_consolidated_page('Portofoliu Clienți și Concentrare Risc', [...])

# Pagina 5: Tablou Financiar (CONSOLIDAT)
pdf.add_consolidated_page('Tablou Financiar', [
    {'title': 'Indicatori Generali', 'df': results['indicatori_generali'], ...},
    {'title': 'Indicatori Lichiditate', 'df': results['indicatori_lichiditate'], ...},
    # ... celelalte 3 secțiuni
])

# Pagina 6+: Grafice și tabele detaliate (neschimbat)

Structură Finală

PDF (6+ pagini):

Pagina 1: Titlu
Pagina 2: Vedere Executivă (KPIs + YoY + Recomandări)
Pagina 3: Indicatori Venituri (Current + YoY)
Pagina 4: Clienți și Risc (Portofoliu + Concentrare cu YoY)
Pagina 5: Tablou Financiar (5 secțiuni)
Pagina 6+: Grafice și tabele detaliate

Excel (12-15 sheet-uri):

Sheet 1: Vedere Ansamblu (KPIs + YoY + Recomandări)
Sheet 2: Indicatori Venituri (Current + YoY merged)
Sheet 3: Clienți și Risc (Portofoliu + Concentrare + YoY)
Sheet 4: Tablou Financiar (Toate cele 5 secțiuni)
Sheet 5+: Sheet-uri detaliu individuale (neschimbat)

Ordine Implementare

  1. queries.py - Fix CONCENTRARE_RISC_YOY bug (independent)
  2. report_generator.py - Adaugă add_consolidated_sheet() și add_consolidated_page()
  3. main.py - Actualizează sheet_order și legends
  4. main.py - Implementează logica de merge DataFrames pentru consolidări
  5. main.py - Actualizează fluxul Excel cu noile sheet-uri consolidate
  6. main.py - Actualizează fluxul PDF cu noile pagini consolidate
  7. Test - Rulare și verificare output

Note Importante

  1. Păstrează query-urile originale - Nu modificăm SQL-urile (exceptând bug-ul), doar modul de prezentare
  2. Legendele sunt obligatorii - Fiecare secțiune consolidată trebuie să aibă legendă completă
  3. Colorare consistentă: OK=verde, ATENȚIE=galben/portocaliu, ALERTĂ=roșu
  4. Trend YoY: CREȘTERE=verde, SCĂDERE=roșu, STABIL=gri
  5. Date lipsă: Afișează "-" sau "N/A", nu ascunde secțiunea