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>
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_anteriorpoate fi gol (0 vânzări în perioada 12-24 luni)ranked_anteriorva fi golmetrics_anteriorva avea 1 rând dar cu toate valorile NULL- La CROSS JOIN cu metrics_curent, rezultatul are NULLs
- Dar problema reală: când
ranked_anterioreste gol, SUM() în Oracle returnează NULL, nu 0
Soluție Detaliată:
- Redenumește
metrics_anteriorînmetrics_anterior_raw - Adaugă CTE
metrics_anteriorcu 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
)
- Modifică calculul în
combinedsă 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,
- Adaugă coloana
HAS_ANTERIORpentru 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:
- În
main.py: Creează DataFrame combinat dinsumar_executivJOINsumar_executiv_yoype INDICATOR - Apelează noua metodă
add_consolidated_sheet()pentru Excel - 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:
- Merge DataFrames pe
LINIE_BUSINESS - Elimină coloane duplicate
- 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:
- Merge
concentrare_risccuconcentrare_risc_yoype INDICATOR - 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:
- Folosește
add_consolidated_sheet()cu 5 secțiuni - 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,recomandariindicatori_agregati_venituri,indicatori_agregati_venituri_yoyportofoliu_clienti,concentrare_risc,concentrare_risc_yoyindicatori_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
- queries.py - Fix CONCENTRARE_RISC_YOY bug (independent)
- report_generator.py - Adaugă
add_consolidated_sheet()șiadd_consolidated_page() - main.py - Actualizează sheet_order și legends
- main.py - Implementează logica de merge DataFrames pentru consolidări
- main.py - Actualizează fluxul Excel cu noile sheet-uri consolidate
- main.py - Actualizează fluxul PDF cu noile pagini consolidate
- Test - Rulare și verificare output
Note Importante
- Păstrează query-urile originale - Nu modificăm SQL-urile (exceptând bug-ul), doar modul de prezentare
- Legendele sunt obligatorii - Fiecare secțiune consolidată trebuie să aibă legendă completă
- Colorare consistentă: OK=verde, ATENȚIE=galben/portocaliu, ALERTĂ=roșu
- Trend YoY: CREȘTERE=verde, SCĂDERE=roșu, STABIL=gri
- Date lipsă: Afișează "-" sau "N/A", nu ascunde secțiunea