v0.4.0 — fix grant gemelli Schwab persi dal dedup
🐛 Fix
Grant gemelli Schwab persi dal dedup trades. Due RSU grant identici per quantità e calendario di vest, venduti lo stesso giorno allo stesso prezzo, producono sul Year-End Summary di Schwab due righe byte-identiche. La UNIQUE constraint della tabella trades collassava questa coppia in una sola riga, scartando silenziosamente la seconda.
Effetto su Modello Redditi:
- Plusvalenza Quadro RT dimezzata sui lotti gemelli — un solo SELL contava verso il netto
- Posizione fantasma in Quadro RW a fine anno — il secondo BUY restava "non venduto" perché privo del SELL gemello che lo avrebbe consumato, e veniva applicata IVAFE su azioni non più detenute
Il bug ha effetto solo sui lotti fungibili per data di acquisizione, quantità e prezzo di vendita. Utenti con grant a calendario differenziato o con singolo grant non sono toccati. Il path IBKR è anch'esso coperto dal fix, anche se in pratica IBKR esibisce identificatori univoci per trade.
🔧 Changed
Schema SQLite trades. Aggiunta colonna lot_seq INTEGER NOT NULL DEFAULT 0 e sostituzione della UNIQUE constraint inline con UNIQUE INDEX idx_trades_natkey che include lot_seq. Il numero di sequenza è assegnato per-natural-key all'interno di ogni ParsedData dal metodo _store_trades: re-parsare la stessa fonte produce le stesse seq, quindi la deduplica cross-load resta idempotente, ma duplicati genuini provenienti dalla stessa fonte sopravvivono.
Migrazione automatica in place all'apertura dei DB esistenti: la tabella trades viene ricostruita senza la vecchia UNIQUE e con la nuova colonna (legacy rows → lot_seq=0); il successivo decaf load re-parsa la fonte e inserisce le righe seq=1+ mancanti. Nessun intervento manuale richiesto.
Installazione
pip install --upgrade decaf-tax