You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Autofill della dichiarazione precompilata AdE via Chrome DevTools Protocol. Nuovi script python -m decaf.scripts.fill_rw (Quadro RW — monitoraggio fiscale + IVAFE, un rigo per lotto, 5 righi per Modulo) e python -m decaf.scripts.fill_rt_rm (Quadro RT rigo RT11 col.1/col.2 totali plusvalenze 26% + Quadro RM Sez. II-A rigo RM31, un Modulo di Quadro RM per ogni coppia stato estero + tipo reddito). Pilota un Chrome aperto in --remote-debugging-port=9222, popola i campi della React app AdE bypassando il controllo dei controlled inputs (native value setter + invocazione diretta della prop onChange), naviga tra i Moduli rilevando il fallback URL quando la pagina richiesta non esiste ancora ed eseguendo "Aggiungi modulo + Conferma". Convenzioni di sicurezza: rifiuta di sovrascrivere campi pre-esistenti senza --force, abortisce se compare il banner "Salvataggio non effettuato", non clicca mai "Calcola, stampa e invia" — l'invio finale resta sempre una scelta manuale. Helpers CDP condivisi estratti in decaf.scripts._cdp per riuso. Vedi src/decaf/scripts/README.md per prerequisiti, flag e workflow consigliato.
Sezione "Per la dichiarazione precompilata" nei report. CLI, PDF e XLS espongono ora una mappa esplicita decaf → Modello Redditi PF: per ogni rigo/colonna dei quadri RW, RT, RL+RM è indicato il valore EUR e la sua origine nei dati decaf. Confronto fianco-a-fianco tra Opzione A (RL+CE, IRPEF marginale + credito imposta estera) e Opzione B (RM31, sostitutiva 26%) con simulazione del netto pagato in entrambi gli scenari ai tre scaglioni IRPEF (23/35/43%) e break-even aliquota marginale calcolato in automatico — utile per scegliere consapevolmente tra le due vie tassative per i redditi di capitale di fonte estera. Breakdown RM31 per coppia (stato, tipo reddito) con codice paese AdE, importo lordo, imposta sostitutiva, count delle entries aggregate.
decaf archive / decaf unarchive. Pacchettizza in un singolo .tgz lo stato decaf perché sia portabile tra macchine o archiviabile come backup fiscale long-term: ~/.cache/decaf/statements.db, ~/.cache/decaf/ecb_rates.db, eventuali sotto-directory di cache (flexquery/), più qualsiasi directory extra passata via --tree (es. --tree private/ per includere file sorgenti broker + report YAML/PDF/XLS generati). decaf unarchive ripristina i DB in ~/.cache/decaf/ e i tree sotto --target-dir (default: cwd) mantenendo i path originali, rifiutando di sovrascrivere file esistenti senza --force. Il tarball include un metadata.yaml con versione decaf, data di creazione, e indice del contenuto.
Archivio perpetuo XML FlexQuery IBKR su disco. IBKR retiene solo ~365 giorni di storico delle FlexQuery; ad ogni decaf load riuscito via API, _fetch_from_ibkr salva ora una copia gzippata dell'XML scaricato in ~/.cache/decaf/flexquery/ibkr_<account>_<from>_<to>_<fetched_at>.xml.gz (overridabile via --flex-archive-dir). Il salvataggio avviene prima del parsing, quindi anche un XML che decaf non riesce a ingerire sopravvive su disco e può essere riprovato in seguito con decaf load --file. L'account ID viene estratto con un regex senza richiedere un parse completo (fallback a unknown se assente). decaf archive include automaticamente la sotto-directory flexquery/ nei bundle, quindi il backup completo del proprio storico fiscale è una singola invocazione.
src/decaf/country_codes.py: mappa ISO 3166-1 alpha-2 → codice numerico AdE (US=069, IE=040, ...) per i quadri che richiedono il codice ministeriale (RM31 col.2, RW col.4). Esposta come iso_to_ade_country_code().
Fixed
Matching ritenute → redditi nel Quadro RL: doppio pass per evitare collisioni cross-security.compute_rl() accoppia ora ogni entry di tipo Withholding con la corrispondente entry di reddito in due passate: (1) strong match — stesso description + stessa date_time (caso dividendi: WHT e dividendo postano lo stesso giorno con il nome del titolo come description), OPPURE stesso tag CREDIT INT FOR <MMM>-<YYYY> (caso interessi broker: la WHT e l'interesse maturato hanno descrizioni parallele del tipo USD CREDIT INT FOR AUG-2025 / WITHHOLDING @ 20% ON CREDIT INT FOR AUG-2025); (2) fallback — stessa valuta + stesso mese, per qualunque WHT non ancora consumata. La logica precedente accoppiava solo per valuta+mese, causando due bug visibili nei broker statement reali: (a) WHT di un dividendo META in trimestre Q1 veniva "rubata" da un credito interessi USD dello stesso mese, lasciando il dividendo con WHT > gross apparente; (b) le quattro WHT trimestrali META si accumulavano tutte sulla prima riga dividendo USA del report. Sei regression test in tests/test_quadro_rl.py coprono i due scenari + casi misti. Effetto sul Modello Redditi: le righe RL e i totali aggregati per RM31 (aggregate_rl_for_rm31) sono ora corretti — chi ha dichiarato anni precedenti con decaf < 0.6.0 e ha dividendi su intermediario estero + interessi sullo stesso conto dovrebbe ri-emettere il report e cross-checkare il Quadro RL/RM rispetto a quanto già dichiarato.
Added (RW autofill — dettagli implementativi)
fill_rw field map RPF26. Il Modulo di Quadro RW contiene 5 righi RW1-RW5; ogni rigo ha le colonne 1 (codice titolare = 1 proprietà), 3 (codice investimento), 4 (codice stato AdE numerico, NON ISO), 5 (% possesso = 100), 6 (criterio determinazione valore = 1 valore di mercato — campo richiesto, non server-computed), 7 (valore iniziale EUR), 8 (valore finale EUR), 10 (giorni di possesso). La colonna 30 (IVAFE dovuta) è computata server-side dopo Salva, non va inserita. Il form rifiuta lo 0 esplicito nel valore iniziale con "formato non corretto" — fill_rw usa un fallback a 1 EUR per i lotti con valore iniziale nullo (lotti acquisiti nello stesso anno di vendita). L'addressing dei field name è RW{row:03d}{col:03d} dove row è 1-5 (rigo dentro il Modulo), NON l'indice del lotto: 23 lotti → 5 Moduli (RW/1..RW/5), con righi sparsi nei vari Moduli.
fill_rt_rm field map RPF26. Quadro RT Sez. II-A 26% = righi RT11..RT16 (non RT21-RT27 della Sez. III-A partecipazioni qualificate). Un unico rigo RT11 aggregato col col.1 = sum(proceeds_eur) e col.2 = sum(cost_basis_eur) su tutti i rt_lines. Quadro RM Sez. II-A: RM31 è un solo rigo per Modulo — sorgenti diverse (interessi USD Schwab, dividendi META USA, interessi EUR IBKR Irlanda) richiedono Moduli di Quadro RM distinti (RM/1, RM/2, RM/3, ...). Field name = RM031{col:03d} dentro ogni Modulo. La colonna 8 (imposta sostitutiva = lordo × 26%) è inserita arrotondata all'intero come da prassi AdE; importi molto piccoli (≤ 0.49 EUR) cadono sullo 0 che il form rifiuta, decaf li scarta ma può essere che il form richieda comunque la colonna — controlla con Verifica i dati. Il form fa fallback alla /RM/N-1 quando si naviga a /RM/N non ancora esistente: fill_rt_rm rileva la condizione confrontando location.pathname dopo il navigate e, se serve, torna alla /RM/N-1 per cliccare "Aggiungi modulo" + "Conferma" prima di scrivere.
Changed
Pre-commit hook allineato al CI. Aggiunto ruff format --check src/ tests/ al pre-commit (.githooks/pre-commit), per allineare le check eseguite localmente prima di un commit a quelle che girano in CI. Prima passava solo ruff check (lint), per cui un drift di formattazione (es. una await cdp.eval_js(...) spezzata su tre righe sotto i 100 char) sfuggiva al commit ma bloccava CI al push.