Files
gepafin-rendicontazione-api/app/templates.py
BFLOWS f9f543b008 feat(istruttoria): verifica riga-per-riga con dual declared/verified
Replica il workflow del foglio Excel originale (REMISSIONE_DEL_DEBITO_5888.xlsm).
Istruttore ora verifica ogni fattura, ogni dipendente ULA, ogni documento singolarmente
invece di accettare/respingere la pratica intera.

Modello dati - nuove colonne su 3 tabelle:
- remission_invoice: taxable_verified, vat_verified, total_verified,
  verification_status (PENDING/AMMESSA/PARZIALE/RESPINTA), verification_notes,
  date_checks (JSONB con invoice_in_period/payment_in_period), verified_by, verified_at
- remission_ula_employee: fte_pct_verified, verification_status, verification_notes,
  verified_by, verified_at
- remission_document: verification_status (PENDING/VALIDO/NON_VALIDO/SCADUTO),
  verification_notes, verified_by, verified_at
- remission_practice: instructor_final_notes, instructor_checklist (JSONB 3 gate SI/NO),
  verbale_date

Nuovi endpoint:
- PUT /instructor/{id}/invoices/{inv_id}/verify (status + rettifica importi + note)
- PUT /instructor/{id}/ula-employees/{emp_id}/verify (rettifica FTE + note)
- PUT /instructor/{id}/documents/{doc_code}/verify (VALIDO/NON_VALIDO/SCADUTO + note)
- PUT /instructor/{id}/final-notes (note sintetiche + checklist)

Ricalcolo gate_check dual track:
- grand_total_declared: sempre (importo richiesto dal beneficiario)
- grand_total_verified: somma solo fatture AMMESSA/PARZIALE (se PARZIALE usa verified)
- remission_due: usa verified se any_verified=True, altrimenti declared (backward compat)
- residuo_da_restituire: amount_erogato - remission_due
- flag any_verified e all_verified per gating decisione finale

_auto_check_dates: fattura in periodo? pagamento in periodo?
Legge period_start e period_end da schema.gate_rules (superadmin editor).

Template: aggiunto period_start/period_end_date come campi 'editable_by superadmin'
nella sezione general static_fields.

Schema editor FE (BandoRendicontazioneSchemaEdit): aggiunto Calendar period_start
accanto a period_end in section gate rules. period_start_rule dropdown per logica
(erogato_date|fixed) resta; period_start data fissa usata dal check.
2026-04-18 11:03:15 +02:00

130 lines
5.6 KiB
Python

"""
Template schemi precompilati per bandi noti.
RE-START: il bando del xlsx di Cecilia, base per la prima iterazione.
"""
RESTART_TEMPLATE = {
"version": "1.0",
"template_id": "RESTART_V1",
"template_label": "RE-START (fondo prestiti con remissione del debito)",
"sections": [
{
"type": "static_fields",
"id": "general",
"label": "Dati generali",
"description": "Regime IVA, dati base del beneficiario, periodo di ammissibilità delle spese.",
"fields": [
{
"id": "period_start_date",
"type": "date",
"label": "Periodo ammissibilità — Data inizio",
"description": "Data minima di emissione/pagamento fatture ammissibili. Di norma: data erogazione del finanziamento.",
"editable_by": "superadmin",
"required": True
},
{
"id": "period_end_date",
"type": "date",
"label": "Periodo ammissibilità — Data fine",
"description": "Data massima di emissione/pagamento fatture ammissibili.",
"editable_by": "superadmin",
"required": True
},
{
"id": "iva_regime",
"type": "select",
"label": "Regime IVA",
"required": True,
"options": [
{"value": "ORDINARIO", "label": "Ordinario — IVA non ammissibile"},
{"value": "FORFETTARIO", "label": "Forfettario — IVA ammissibile"},
{"value": "ESENTE", "label": "Esente"},
],
"help": "Il regime IVA determina se l'IVA delle fatture è rendicontabile. In regime ordinario vale solo l'imponibile.",
}
],
},
{
"type": "category_grid",
"id": "expenses",
"label": "Spese ammissibili per categoria",
"description": "Carica le fatture dentro la categoria appropriata. Totali parziali e complessivo calcolati in tempo reale.",
"categories": [
{
"code": "B1",
"label": "Tecnologie innovative (Industry 4.0, digitale)",
"description": "Hardware, software, soluzioni innovative destinate ad attività produttive",
"cap_amount": None,
},
{
"code": "B2",
"label": "Incremento ULA (occupazione)",
"description": "Costi del personale collegati a incremento di occupazione",
"cap_amount": None,
},
{
"code": "B3",
"label": "Formazione",
"description": "Corsi, docenze, materiali didattici per il personale",
"cap_amount": None,
},
],
"invoice_schema": {
"required_fields": [
"invoice_number",
"invoice_date",
"payment_date",
"supplier_name",
"supplier_vat",
"description",
"taxable",
"vat",
"total",
"pdf",
],
"optional_fields": ["vat_rate", "vat_exempt_reason"],
},
},
{
"type": "ula_block",
"id": "ula",
"label": "Calcolo ULA (incremento occupazione)",
"description": "Per ogni dipendente: codice fiscale, tipologia contratto, percentuale di tempo, periodo. Allegato di supporto obbligatorio (LUL, estratto gestionale, dichiarazione del consulente del lavoro).",
"enabled": True,
"threshold": 1.0,
"period_start_rule": "erogato_date",
"period_end": "2021-12-31",
"supporting_doc_required": True,
"supporting_doc_types": [
{"code": "LUL", "label": "Libro Unico del Lavoro"},
{"code": "GESTIONALE_PAGHE", "label": "Estratto gestionale paghe"},
{"code": "DICHIARAZIONE_CDL", "label": "Dichiarazione Consulente del Lavoro"},
{"code": "ALTRO", "label": "Altro documento di supporto"},
],
},
{
"type": "document_checklist",
"id": "docs",
"label": "Documenti richiesti",
"description": "I documenti già in regola nel repository della Company saranno riutilizzati (semaforo verde). Solo quelli scaduti o mancanti richiedono caricamento.",
"required_types": [
{"code": "DURC", "label": "DURC (Documento Unico di Regolarità Contributiva)"},
{"code": "VISURA_CAMERALE", "label": "Visura camerale aggiornata"},
{"code": "BILANCIO", "label": "Bilancio ultimo esercizio"},
{"code": "ANTIRICICLAGGIO", "label": "Dichiarazione antiriciclaggio"},
],
},
],
"gate_rules": {
"amount_range": {"min": 5000, "max": 25000},
"cap_pct_erogato": 0.5,
"cap_absolute": 12500,
"iva_ordinario_imponibile_only": True,
"period_start_rule": "erogato_date",
"period_end": "2021-12-31",
"require_at_least_one_invoice_per_nonzero_category": True,
"require_ula_above_threshold": True,
"require_all_documents_resolved": True,
},
}