diff --git a/app/routers/verbale.py b/app/routers/verbale.py index c28a3ae..08ef456 100644 --- a/app/routers/verbale.py +++ b/app/routers/verbale.py @@ -16,7 +16,7 @@ from sqlalchemy import text from ..db import get_db from ..auth import AuthUser, get_current_user -from ..models import RemissionPractice +from ..models import RemissionPractice, RemissionCustomCheckValue from .practices import _compute_gate_check router = APIRouter(prefix="/api/remission-practices/instructor", tags=["verbale"]) @@ -177,6 +177,50 @@ def _build_context(db: Session, practice: RemissionPractice, user: AuthUser) -> """), {"uid": user.user_id}).scalar() instructor_name = row + # v2: custom_checks merged (schema_snapshot.custom_checks[] + RemissionCustomCheckValue) + check_defs = practice.schema_snapshot.get("custom_checks") or [] + values_by_code = {v.check_code: v for v in practice.custom_checks} + custom_checks_merged = [] + for d in check_defs: + code = d.get("code") + val = values_by_code.get(code) + custom_checks_merged.append({ + "code": code, + "label": d.get("label"), + "description": d.get("description"), + "requires_document": bool(d.get("requires_document")), + "required": bool(d.get("required")), + "beneficiary_declared": bool(val.beneficiary_declared) if val else False, + "declared_at": val.declared_at if val else None, + "has_document": bool(val and val.storage_path), + "verification_status": (val.verification_status if val else "PENDING"), + "verification_notes": (val.verification_notes if val else None), + }) + + # v2: storico tranche precedenti APPROVED (se sequence > 1) + previous_tranches = [] + cumulative_approved = 0.0 + if practice.sequence_number > 1: + prevs = db.query(RemissionPractice).filter( + RemissionPractice.application_id == practice.application_id, + RemissionPractice.sequence_number < practice.sequence_number, + RemissionPractice.status == "APPROVED", + ).order_by(RemissionPractice.sequence_number).all() + for pv in prevs: + amt = float(pv.approved_remission or 0) + cumulative_approved += amt + previous_tranches.append({ + "sequence_number": pv.sequence_number, + "period_label": pv.period_label, + "reviewed_at": pv.reviewed_at, + "approved_remission": amt, + "cumulative": cumulative_approved, + }) + + # v2 max_tranches dallo schema_snapshot (o dal bando corrente, fallback 1) + snap_rules = practice.schema_snapshot.get("gate_rules") or {} + max_tranches_snapshot = int(snap_rules.get("max_tranches") or totals.get("tranches_max") or 1) + return { "practice": practice, "totals": totals, @@ -196,6 +240,10 @@ def _build_context(db: Session, practice: RemissionPractice, user: AuthUser) -> "company": company, "instructor_name": instructor_name, "generated_at": datetime.now().strftime("%d/%m/%Y"), + # v2 + "custom_checks_merged": custom_checks_merged, + "previous_tranches": previous_tranches, + "max_tranches_snapshot": max_tranches_snapshot, } @@ -234,7 +282,7 @@ def verbale_pdf( practice, html = _render_html(db, practice_id, user) pdf_bytes = WeasyHTML(string=html).write_pdf() - filename = f"verbale_istruttoria_pratica_{practice.application_id}.pdf" + filename = f"verbale_istruttoria_pratica_{practice.application_id}_t{practice.sequence_number}.pdf" return Response( content=pdf_bytes, media_type="application/pdf", diff --git a/app/templates_jinja/verbale_istruttoria.html b/app/templates_jinja/verbale_istruttoria.html index 2c54f5c..b5addb5 100644 --- a/app/templates_jinja/verbale_istruttoria.html +++ b/app/templates_jinja/verbale_istruttoria.html @@ -182,7 +182,8 @@
Nessun documento richiesto dallo schema del bando.
{% endif %} +{# ============ CONTROLLI AGGIUNTIVI ============ #} +{% if custom_checks_merged %} +| Controllo | +Obbligatorio | +Dichiarato | +Doc. allegato | +Validazione | +Note istruttore | +
|---|---|---|---|---|---|
|
+ {{ cc.label or cc.code }}
+ {% if cc.description %} {{ cc.description|truncate(180) }}{% endif %} + |
+ {% if cc.required %}SÌ{% else %}opzionale{% endif %} | +{% if cc.beneficiary_declared %}SÌ{% else %}NO{% endif %} | ++ {% if cc.requires_document %} + {% if cc.has_document %}SÌ{% else %}NO{% endif %} + {% else %}non richiesto{% endif %} + | +{{ stat }} | +{{ cc.verification_notes or '—' }} | +
| # | +Periodo / fase | +Data approvazione | +Importo ammesso | +Cumulativo | +
|---|---|---|---|---|
| T{{ t.sequence_number }} | +{{ t.period_label or '—' }} | +{{ t.reviewed_at|datefmt }} | +{{ t.approved_remission|euro }} | +{{ t.cumulative|euro }} | +