From a2ad4c7ed24b6194bc2eacfa45103a011697016f Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Tue, 9 Dec 2025 16:30:12 +0200 Subject: [PATCH] Add implementation plan for report consolidation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- PLAN_CONSOLIDARE_RAPOARTE.md | 346 +++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 PLAN_CONSOLIDARE_RAPOARTE.md diff --git a/PLAN_CONSOLIDARE_RAPOARTE.md b/PLAN_CONSOLIDARE_RAPOARTE.md new file mode 100644 index 0000000..f0dd5d3 --- /dev/null +++ b/PLAN_CONSOLIDARE_RAPOARTE.md @@ -0,0 +1,346 @@ +# 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: +```sql +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 +) +``` +3. **Modifică** calculul în `combined` să trateze cazul când total anterior = 0: +```sql +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, +``` +4. **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ă:** +```python +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ă:** +```python +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ă: + +```python +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: + +```python +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): + +```python +# 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