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>
This commit is contained in:
346
PLAN_CONSOLIDARE_RAPOARTE.md
Normal file
346
PLAN_CONSOLIDARE_RAPOARTE.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user