netgescon-day0/docs/support/MINI-AI-202-RICONCILIAZIONE-RUNBOOK.md

18 KiB
Executable File

Mini AI .202 - riconciliazione banca/incassi

Obiettivo

Usare la macchina .202 come motore di suggerimenti per riconciliare incassi, movimenti bancari e scritture contabili. La mini AI non deve scrivere sul gestionale: deve restituire proposte controllabili dall'operatore.

Primo perimetro reale

  • Stabile: 0016 / stabile_id=17
  • Fonte incassi iniziale: netgescon.incassi, importata da singolo_anno.mdb.incassi
  • Fonte movimenti banca: contabilita_movimenti_banca, import Fucino validato
  • Stato in_da_ec: opzionale; se vuota, il payload usa automaticamente netgescon.incassi

Configurazione NetGescon

Sul nodo applicativo impostare:

MINI_AI_ENABLED=true
MINI_AI_BASE_URL=http://192.168.0.202:8000
MINI_AI_RECONCILIATION_PATH=/api/v1/reconciliation/incassi
MINI_AI_TIMEOUT=30

Se la mini AI espone autenticazione bearer, aggiungere anche:

MINI_AI_TOKEN=<token locale della macchina .202>

Poi eseguire:

php artisan config:clear
php artisan netgescon:mini-ai-incassi --codice-stabile=0016 --limit=2 --dry-run
php artisan netgescon:mini-ai-incassi --codice-stabile=0016 --limit=20

Se la UI admin-filament/contabilita/incassi mostra Mini AI non abilitata, il controllo locale e:

php artisan tinker --execute='dump(config("services.mini_ai"));'
php artisan config:clear

La pagina salva comunque la richiesta in ai_requests, ma non prova la POST verso .202 finche MINI_AI_ENABLED=true non e attivo.

Endpoint atteso su .202

La macchina .202 deve esporre:

POST /api/v1/reconciliation/incassi

Input: JSON prodotto da NetGescon con:

  • task = reconcile_incassi_movimenti_bancari
  • mode = read_only_suggestions
  • snapshot.meta
  • snapshot.records[]
  • snapshot.records[].payer_reference quando il bonifico contiene Coord.Ordinante, Banca Ordinante, Cro

Output richiesto:

{
  "summary": "string",
  "warnings": ["string"],
  "suggestions": [
    {
      "legacy_key": "inc:11172",
      "confidence": 0.82,
      "suggested_incasso_id": 11172,
      "suggested_movimento_id": 15800,
      "suggested_action": "review",
      "reason": "Importo coincidente; data lontana, richiede controllo umano.",
      "allocations": [
        {
          "rate_id": 42230,
          "amount": 177.00,
          "ci": "C",
          "gestione": "2024/25",
          "reason": "Acconto gestione corrente indicato nella causale."
        }
      ]
    }
  ]
}

Regole operative HUB incassi

  • La coda operativa deve mostrare solo movimenti banca interni alla finestra delle gestioni ordinarie aperte.
  • Per lo stabile 0016 la finestra verificata e 2024/25 + 2025/26; la UI deve poter comunque spostare la competenza sulla gestione chiusa immediatamente precedente 2023/24 quando la causale banca indica saldi o conguagli dell anno precedente.
  • I riferimenti Coord.Ordinante, Banca Ordinante, BIC/SWIFT e CRO vanno trattati come indizi forti: se l operatore conferma il soggetto corretto, il mapping deve essere memorizzato per accelerare i pagamenti successivi della stessa banca/IBAN.
  • Nel blocco C/I dell HUB il nominativo operatore deve seguire questo ordine: unita_immobiliari.denominazione, poi gescon_import.condomin.nom_cond, solo in ultima istanza soggetti legacy.
  • Le spese straordinarie aperte vanno tenute in una sezione separata dalle rate ordinarie e devono restare visibili fino a chiusura effettiva, anche se la coda operativa ordinaria lavora su una finestra di gestioni piu stretta.
  • Nel riepilogo del C/I il gestionale deve esporre anche i parziali del dovuto per tipo (ordinarie / straordinarie), per gestione e il totale generale dovuto: servono per solleciti e chiusure contabili in partita doppia.
  • Se una gestione straordinaria esiste in gestioni_contabili / lavori_straordinari ma non produce righe residue sull interno, la UI deve segnalarla come possibile buco di import/materializzazione delle spese straordinarie.

Azioni ammesse:

  • link: proposta molto forte, comunque da confermare in NetGescon
  • review: caso plausibile ma da verificare
  • ignore: non sembra riconciliabile
  • duplicate: sospetto duplicato o movimento gia coperto

Prompt da dare all'agent sulla .202

Sei la mini AI banca/contabilita di NetGescon. Devi esporre un servizio HTTP locale su /api/v1/reconciliation/incassi che riceve snapshot JSON read-only da NetGescon.

Regole:
- Non scrivere mai sul gestionale.
- Non chiamare API di update.
- Restituisci solo suggerimenti JSON.
- Usa importo, data, descrizione, nominativo, scala/interno, ricevuta, protocollo e candidati movimento.
- Le spese bancarie ricorrenti, bolli, commissioni e canoni banca vanno classificate come casi facili ma non collegate a incassi condominiali.
- I CBILL vanno riconosciuti dal codice/causale quando presente.
- Se la confidenza e bassa o ci sono piu candidati simili, usa suggested_action=review.
- Se un movimento sembra gia registrato o duplicato, usa suggested_action=duplicate.
- Rispondi sempre con JSON valido: summary, warnings, suggestions[].

Schema suggestion:
legacy_key, confidence, suggested_incasso_id, suggested_movimento_id, suggested_action, reason, allocations[].

Quando il record contiene `candidate_rates`, devi valorizzare `allocations[]` con il sottoinsieme di rate selezionato. Ogni elemento deve contenere almeno: `rate_id`, `amount`, `ci`, `gestione`, `reason`.

Nella UI di NetGescon, le allocazioni della risposta vengono mostrate nel pannello mini AI e possono essere trasferite sulle imputazioni manuali del movimento selezionato con il comando `Applica allocazioni AI alle rate`.
La chiusura della riconciliazione resta comunque bloccata alla quadratura esatta tra importo banca e totale imputato.

Apprendimento progressivo

Nella prima fase l'apprendimento avviene salvando:

  • payload inviato in ai_requests.request_text
  • risposta in ai_requests.response_text
  • feedback operatore nella UI incassi / feedback AI

Solo dopo una serie di risposte corrette si potra introdurre una tabella regole o una memoria dedicata per pattern ricorrenti come spese bancarie, CBILL, MAV e bonifici con causali standard.

Servizio persistente su .202 con systemd

Quando l'endpoint risponde correttamente ai test manuali, renderlo persistente con systemd. Esempio di unit, da adattare al percorso reale dell'app mini AI sulla .202:

[Unit]
Description=NetGescon Mini AI Reconciliation API
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=michele
WorkingDirectory=/home/michele/mini-ai-reconciliation
Environment=MINI_AI_TOKEN=
ExecStart=/home/michele/mini-ai-reconciliation/.venv/bin/uvicorn app:app --host 0.0.0.0 --port 8000 --workers 2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Comandi sulla .202:

sudo nano /etc/systemd/system/netgescon-mini-ai.service
sudo systemctl daemon-reload
sudo systemctl enable --now netgescon-mini-ai.service
sudo systemctl status netgescon-mini-ai.service
journalctl -u netgescon-mini-ai.service -f

Se si abilita token bearer, impostare MINI_AI_TOKEN nella unit e configurare lo stesso valore sul nodo NetGescon con MINI_AI_TOKEN=<token>. Non salvare token nei documenti o in chat.

Caso guida: Barone Michele, bonifico 1.285,70

Movimento banca reale:

  • contabilita_movimenti_banca.id = 15523
  • data 2025-01-16
  • importo 1.285,70
  • descrizione banca:
BONIFICO A VOSTRO FAVORE NETHOME DI BARONE MICHELE E C. SOCI Data Regolamento: 16/01/25 Coord.Ordinante: IT85 H010 3003 2710 0000 1540 577 Banca Ordinante: 01030/01697-PASCITMM Cro: A100267492801030480320003200IT Note: SALDO CONDOMINIO ANNO 2024 E ACC.TO 2025 E/C R IF. sc.B int.4 BARONE MICHELE Id.Operazione: 277385815

Comando NetGescon per generare il payload:

php artisan netgescon:mini-ai-incassi --movimento-id=15523 --limit=30 --dry-run > payload-barone-15523.json
curl -sS -X POST 'http://192.168.0.202:8000/api/v1/reconciliation/incassi' \
  -H 'Content-Type: application/json' \
  -d @payload-barone-15523.json

Regola attesa:

  • leggere sc.B int.4 e BARONE MICHELE
  • attribuire il movimento al ramo C se le rate candidate sono ci=C
  • interpretare SALDO CONDOMINIO ANNO 2024 E ACC.TO 2025 come:
    • saldo gestione chiusa/adiacente 2023/24
    • acconto gestione corrente 2024/25
  • non andare su gestioni molto vecchie
  • non selezionare rate successive al pagamento se esiste una combinazione esatta sulle rate gia emesse alla data del versamento
  • scegliere la combinazione che torna a 1.285,70

Allocazione attesa per il caso Barone:

{
  "legacy_key": "mov:15523",
  "confidence": 0.98,
  "suggested_incasso_id": null,
  "suggested_movimento_id": 15523,
  "suggested_action": "link",
  "reason": "La causale indica saldo condominio anno 2024 e acconto 2025; scala/interno e nominativo coincidono; la somma delle rate selezionate coincide con il bonifico.",
  "allocations": [
    {
      "rate_id": 41225,
      "amount": 87.84,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "Conguaglio esercizio precedente, saldo anno 2024."
    },
    {
      "rate_id": 41457,
      "amount": 87.84,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "Conguaglio esercizio precedente, saldo anno 2024."
    },
    {
      "rate_id": 41261,
      "amount": 87.84,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "Conguaglio esercizio precedente, saldo anno 2024."
    },
    {
      "rate_id": 41077,
      "amount": 241.00,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "Rata giugno-luglio 2024 inclusa nel saldo anno 2024."
    },
    {
      "rate_id": 41517,
      "amount": 241.00,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "Rata agosto-settembre 2024 inclusa nel saldo anno 2024."
    },
    {
      "rate_id": 42230,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "Prima rata gestione 2024/25, acconto 2025."
    },
    {
      "rate_id": 42276,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "Seconda rata gestione 2024/25, acconto 2025."
    },
    {
      "rate_id": 41668,
      "amount": 93.09,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "ATTO AeR ricevuto 05/07/24, prima rata."
    },
    {
      "rate_id": 41597,
      "amount": 93.09,
      "ci": "C",
      "gestione": "2023/24",
      "reason": "ATTO AeR ricevuto 05/07/24, seconda rata."
    }
  ]
}

Somma attesa allocations.amount: 1.285,70.

Nota per l'agent .202: nel payload Barone sono presenti anche rate candidate non selezionate. Non vanno scelte se non servono alla quadratura o se sono fuori dalla causale. In particolare, con questa causale non selezionare rate provvisorie vecchie o la 3/6 Rata FEBBRAIO-MARZO 25 se la combinazione sopra quadra gia esattamente.

Caso guida: Barone Michele, bonifico 960,79

Movimento banca reale:

  • contabilita_movimenti_banca.id = 15953
  • data 2025-12-23
  • importo 960,79
  • descrizione banca:
BONIFICO A VOSTRO FAVORE NETHOME DI BARONE MICHELE E C. SOCI Data Regolamento: 23/12/25 Coord.Ordinante: IT85 H010 3003 2710 0000 1540 577 Banca Ordinante: 01030/01697-PASCITMM Cro: A108446418101030480320003200IT Note: SALDO CONDOMINIO ANNO 2025 E ACC.TO 2026 E/C R IF. sc.B int.4 BARONE MICHELE Id.Operazione: 304017429

Comando NetGescon per generare il payload:

php artisan netgescon:mini-ai-incassi --movimento-id=15953 --limit=40 --dry-run > payload-barone-15953.json
curl -sS -X POST 'http://192.168.0.202:8000/api/v1/reconciliation/incassi' \
  -H 'Content-Type: application/json' \
  -d @payload-barone-15953.json

Regola attesa:

  • leggere sc.B int.4 e BARONE MICHELE
  • attribuire il movimento al ramo C se le rate candidate sono ci=C
  • interpretare SALDO CONDOMINIO ANNO 2025 E ACC.TO 2026 come:
    • saldo gestione 2024/25
    • acconto gestione 2025/26
  • includere i conguagli negativi se servono alla quadratura
  • non selezionare rate successive non necessarie se esiste una combinazione esatta
  • scegliere la combinazione che torna a 960,79

Allocazione attesa:

{
  "legacy_key": "mov:15953",
  "confidence": 0.98,
  "suggested_incasso_id": null,
  "suggested_movimento_id": 15953,
  "suggested_action": "link",
  "reason": "La causale indica saldo condominio anno 2025 e acconto 2026; scala/interno e nominativo coincidono; la somma delle rate selezionate coincide con il bonifico.",
  "allocations": [
    {
      "rate_id": 41878,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "3/6 rata gestione 2024/25, saldo anno 2025."
    },
    {
      "rate_id": 42355,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "4/6 rata gestione 2024/25, saldo anno 2025."
    },
    {
      "rate_id": 42546,
      "amount": -0.61,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "Conguaglio negativo da includere nella quadratura."
    },
    {
      "rate_id": 42468,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "5/6 rata gestione 2024/25, saldo anno 2025."
    },
    {
      "rate_id": 42706,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "6/6 rata gestione 2024/25, saldo anno 2025."
    },
    {
      "rate_id": 42803,
      "amount": 177.00,
      "ci": "C",
      "gestione": "2025/26",
      "reason": "Prima rata gestione 2025/26, acconto 2026."
    },
    {
      "rate_id": 42134,
      "amount": 38.20,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "Lav. facciata lato parrocchia, prima rata capitolato."
    },
    {
      "rate_id": 42194,
      "amount": 38.20,
      "ci": "C",
      "gestione": "2024/25",
      "reason": "Lav. facciata lato parrocchia, seconda rata capitolato."
    }
  ]
}

Somma attesa allocations.amount: 960,79.

Nota per l'agent .202: nel payload mov:15953 sono presenti anche rate candidate non selezionate, come 1/6 e 2/6 2024/25 o rate successive 2025/26. Non vanno scelte se il saldo indicato dalla causale quadra gia con la combinazione sopra.

BUG risolto nel primo collaudo

Il payload da 20 righe supera 64 KB; ai_requests.request_text e response_text devono essere LONGTEXT. La migration 2026_06_07_130000_expand_ai_requests_text_columns.php applica questa correzione.

Collaudo end-to-end 07/06/2026

Endpoint .202 verificato:

POST http://192.168.0.202:8000/api/v1/reconciliation/incassi

Esito con payload di esempio fornito dall'agent .202:

  • HTTP 200
  • risposta valida con summary, warnings, suggestions[]
  • match forte su esempio inc:11172 -> movimento 15800, confidence=0.99, suggested_action=link

Esito con payload reale prodotto da NetGescon:

MINI_AI_ENABLED=true MINI_AI_BASE_URL=http://192.168.0.202:8000 MINI_AI_RECONCILIATION_PATH=/api/v1/reconciliation/incassi php artisan netgescon:mini-ai-incassi --codice-stabile=0016 --limit=2
  • ai_request_id=2
  • risposta ricevuta e salvata in ai_requests
  • status=answered
  • request_len=4600
  • response_len=734
  • risposta: 2 record analizzati; 2 review
  • suggerimenti su inc:11172 -> movimento 15800 e inc:11170 -> movimento 15822, entrambi confidence=0.45 e suggested_action=review

Interpretazione: il collegamento funziona. La qualita del suggerimento e volutamente prudente per i primi dati reali, perche i candidati hanno importi uguali ma date distanti o ambigue.

Esito successivo con payload movimento Barone:

  • comando: php artisan netgescon:mini-ai-incassi --movimento-id=15523 --limit=30
  • richiesta generata: legacy_key=mov:15523, candidate_rates=14
  • risposta .202 attuale: link al movimento con confidence=0.99, ma senza allocations[]
  • prossimo aggiornamento richiesto all'agent .202: usare candidate_rates e restituire la scomposizione rate nel formato indicato sopra.

Esito con payload movimento Barone 960,79:

  • comando: php artisan netgescon:mini-ai-incassi --movimento-id=15953 --limit=40
  • richiesta generata: legacy_key=mov:15953, candidate_rates=12
  • risposta .202 attuale: link al movimento con confidence=0.99, ma allocations=[]
  • prossimo aggiornamento richiesto all'agent .202: includere conguagli negativi e selezionare il sottoinsieme esatto da 960,79.

Caso guida: Caschetto Lucia / Curatola Antonio, bonifico 1.968,23

Movimento banca reale:

  • contabilita_movimenti_banca.id = 15803
  • data 2026-04-30
  • importo 1.968,23
  • descrizione banca:
BONIFICO A VOSTRO FAVORE CURATOLA ANTONIO Data Regolamento: 30/04/26 Coord.Ordinante: IT57 F020 0805 2120 0000 3789 819 Banca Ordinante: 01020/02080-UNCRITMM Cro: 1101261190461826 Note: estratto conto condominiale Germanico 96 del 0 8.04.2026 Id.Operazione: NOTPROVIDED

Particolarita anagrafica:

  • il bonifico non indica B/18
  • il nominativo banca e Curatola Antonio
  • nel legacy l'unita corretta e B/18 - Caschetto Lucia
  • gescon_import.condomin.presso = c/o Avv. Curatola
  • gescon_import.condomin.e_mail_condomino contiene curatola.antonio@libero.it,lcaschetto@gmail.com

Regola attesa:

  • usare presso ed email come alias di riconoscimento, senza cambiare il nominativo principale della unita
  • mantenere Caschetto Lucia come intestatario principale
  • usare le rate candidate ci=C
  • scegliere tutte le 12 rate candidate perche la somma coincide con 1.968,23

Esito test NetGescon:

php artisan netgescon:mini-ai-incassi --movimento-id=15803 --limit=40 --dry-run
  • legacy_key=mov:15803
  • nominativo=Caschetto Lucia
  • scala=B, interno=18
  • candidate_rates=12
  • somma candidate 1.968,23

Esito .202 dopo aggiornamento agent:

  • ai_request_id=5
  • confidence=0.98
  • suggested_action=link
  • allocations[] valorizzato con le 12 rate candidate
  • risposta corretta per il primo caso con alias presso/email