102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
"""queries/report.py — sessione_changes con join sessione"""
|
|
|
|
from .db import query, e, dt, d, badge
|
|
|
|
|
|
def get_report(db_path: str, da_data: str = None, a_data: str = None) -> list:
|
|
"""
|
|
Restituisce sessione_changes JOIN sessione, opzionalmente filtrate per data.
|
|
Ordinate dalla più recente.
|
|
"""
|
|
params = []
|
|
where = []
|
|
if da_data:
|
|
where.append("sc.rilevato_at >= ?")
|
|
params.append(da_data)
|
|
if a_data:
|
|
where.append("sc.rilevato_at <= ?")
|
|
params.append(a_data + " 23:59:59")
|
|
|
|
where_sql = ("WHERE " + " AND ".join(where)) if where else ""
|
|
|
|
sql = f"""
|
|
SELECT
|
|
sc.id AS change_id,
|
|
sc.change_type,
|
|
sc.campo,
|
|
sc.valore_prec,
|
|
sc.valore_nuovo,
|
|
sc.rilevato_at,
|
|
sc.rpa_process_id,
|
|
s.id AS sessione_id,
|
|
s.corso,
|
|
s.variante,
|
|
s.modalita_cod,
|
|
s.modalita_desc,
|
|
s.monte_ore,
|
|
s.soggetto_formatore,
|
|
s.azienda,
|
|
s.articolo_cod,
|
|
s.articolo_desc,
|
|
s.requisiti_formativi_id,
|
|
s.requisiti_formativi_desc,
|
|
(SELECT MIN(sl.data) FROM sessione_lezione sl WHERE sl.sessione_id = s.id) AS prima_lezione
|
|
FROM sessione_changes sc
|
|
LEFT JOIN sessione s ON s.id = sc.sessione_id
|
|
{where_sql}
|
|
ORDER BY sc.rilevato_at DESC
|
|
"""
|
|
return query(db_path, sql, tuple(params))
|
|
|
|
|
|
def get_stats(db_path: str, da_data: str = None, a_data: str = None) -> dict:
|
|
rows = get_report(db_path, da_data, a_data)
|
|
nuovi = sum(1 for r in rows if r['change_type'] == 'nuovo')
|
|
cambiati = sum(1 for r in rows if r['change_type'] == 'modificato')
|
|
return {'report_nuovi': nuovi, 'report_cambiati': cambiati, 'report_total': len(rows)}
|
|
|
|
|
|
def render_table(rows: list) -> str:
|
|
if not rows:
|
|
return '<table><thead><tr><th colspan="11">Nessun dato</th></tr></thead><tbody></tbody></table>'
|
|
|
|
def row_html(r):
|
|
tag = badge('ok', 'Nuovo') if r['change_type'] == 'nuovo' else badge('warn', 'Modificato')
|
|
campo = e(r['campo']) if r['campo'] else '-'
|
|
prec = e(r['valore_prec']) if r['valore_prec'] else '-'
|
|
nuovo = e(r['valore_nuovo']) if r['valore_nuovo'] else '-'
|
|
sid = e(r['sessione_id'])
|
|
return (
|
|
f'<tr data-tipo="{e(r["change_type"])}">'
|
|
f'<td>{tag}</td>'
|
|
f'<td>{sid}</td>'
|
|
f'<td>{e(r["corso"])}</td>'
|
|
f'<td>{e(r["azienda"])}</td>'
|
|
f'<td>{e(r["articolo_cod"])}</td>'
|
|
f'<td class="col-prima-lez">{d(r["prima_lezione"])}</td>'
|
|
f'<td>{campo}</td>'
|
|
f'<td class="val-prec">{prec}</td>'
|
|
f'<td class="val-nuovo">{nuovo}</td>'
|
|
f'<td>{dt(r["rilevato_at"])}</td>'
|
|
f'<td><button class="doc-btn" data-sid="{sid}" data-corso="{e(r["corso"])}" title="Documenti caricati">📄</button></td>'
|
|
f'</tr>'
|
|
)
|
|
|
|
thead = (
|
|
'<thead><tr>'
|
|
'<th>Tipo</th>'
|
|
'<th>ID Sessione</th>'
|
|
'<th>Corso</th>'
|
|
'<th>Azienda</th>'
|
|
'<th>Articolo</th>'
|
|
'<th>Prima Lezione</th>'
|
|
'<th>Campo</th>'
|
|
'<th>Valore Precedente</th>'
|
|
'<th>Valore Nuovo</th>'
|
|
'<th>Rilevato</th>'
|
|
'<th></th>'
|
|
'</tr></thead>'
|
|
)
|
|
tbody = '<tbody>' + ''.join(row_html(r) for r in rows) + '</tbody>'
|
|
return f'<table>{thead}{tbody}</table>'
|