Salta al contenuto principale

Importa un CSV bancario in Beancount con bea

Importa un CSV bancario nel tuo ledger Beancount con bea: mappa le colonne, categorizza con le regole, visualizza in anteprima le voci, controlla i duplicati, poi applicali.

Un ordinario CSV bancario non richiede un importer Python. Mappa le sue colonne con --csv, assegna il nome del conto sorgente con --account, categorizza le righe con --rules, quindi visualizza in anteprima e applica le scritture con bea import.

Serve un libro contabile esistente. Se stai iniziando un nuovo libro, segui la guida rapida CLI. Conserva l'esportazione originale della banca per poterla confrontare con l'anteprima.

1. Mappa le colonne del CSV​

Salva questo esempio come statement.csv, poi esegui i comandi sottostanti dalla stessa directory:

Date,Payee,Narration,Amount
2026-08-02,Whole Foods,groceries,-20.00
2026-08-03,Shell,gas,-40.00
2026-08-04,Unknown Shop,mystery,-9.99

Gli importi usano la convenzione dei segni bancari: la spesa è negativa e un deposito è positivo. La valuta predefinita è la valuta operativa del libro, quindi questo file non richiede una colonna valuta. Inserisci una colonna descrizione bancaria in narration e mantieni payee per il commerciante.

Crea il libro contabile e apri il sotto-conto carburante usato di seguito:

bea --no-input init books --currency USD --date 2026-08-01 \
  --opening-balance "Assets:Checking 1000"
bea --file books/main.bean add open --date 2026-08-01 --account Expenses:Transport:Fuel -c USD

Il modello apre già Expenses:Groceries e gli altri conti comuni. Non apre Expenses:Transport:Fuel, quindi il secondo comando lo apre prima dell'importazione. Opzioni globali come --file vanno prima del sotto-comando.

2. Visualizza in anteprima le scritture​

Salva queste regole di categorizzazione come rules.toml, poi visualizza in anteprima:

cat > rules.toml <<'EOF'
[[rule]]
match = "whole foods|trader joe|corner market"
account = "Expenses:Groceries"
 
[[rule]]
match = "shell|chevron|exxon"
account = "Expenses:Transport:Fuel"
EOF
bea --file books/main.bean import statement.csv --csv date=Date,amount=Amount,payee=Payee,narration=Narration --account Assets:Checking --rules rules.toml

Le regole corrispondono prima al beneficiario, poi alla narrazione, ignorando maiuscole/minuscole. Vince la prima regola che corrisponde. Le righe per cui nessuna regola corrisponde vengono registrate su Expenses:Uncategorized con il flag ! per una revisione successiva. La guida prodotto IMPORTING documenta il riferimento completo di mappatura, incluse la coppia debit e credit, la colonna category e la lettura dell'intestazione --csv auto.

Ancora nulla è scritto nel libro. L'anteprima segnala 3 ready, 0 exact duplicates, 0 possible duplicates ed esce con codice 0. La sua colonna RULE nomina il modello vincente per riga, o unmatched per la riga Unknown Shop. Controlla date, beneficiari, importi firmati sorgente, conti di destinazione, corrispondenze duplicate e differenze di file proposte. Correggi una regola o categoria errata, quindi visualizza di nuovo l'anteprima. Apri eventuali conti mancanti prima di applicare l'importazione: una regola che nomina un conto non aperto dal libro non supera la validazione.

3. Applica le scritture revisionate​

bea --file books/main.bean import statement.csv --apply
bea --file books/main.bean check
bea --file books/main.bean list transaction --flag '!'
bea --file books/main.bean query "SELECT account, sum(position) WHERE account = 'Assets:Checking' GROUP BY account"

La mappatura delle colonne viene memorizzata per libro mastro, riga di intestazione e conto di origine, quindi --apply viene rieseguito senza flag e segnala utilizzando la mappatura delle colonne memorizzata. Ricalcola l'anteprima sui file attuali, convalida il libro mastro completo candidato prima di scrivere e scrive 3 voci. bea check non segnala errori. La coda ! elenca l'unica riga non corrispondente: Unknown Shop con mystery a -9.99 USD. Un controllo superato prova solo che il libro mastro è in equilibrio e convalida. Non dice nulla sul fatto che quella riga appartenga a Expenses:Uncategorized, quindi ricategorizzala deliberatamente nel tuo libro mastro. Il controllo termina a 930.01 USD: il saldo di apertura 1,000 USD meno 69.99 USD di spese.

4. Importazioni ripetute non aggiungono nulla​

bea --file books/main.bean import statement.csv --apply

L'anteprima riporta 0 ready, 3 exact duplicates, e l'esecuzione scrive 0 voci con uscita 0. Ogni riga scritta porta metadati import-id con un hash del contenuto, quindi il file identico corrisponde a ogni riga. Conserva questi metadati quando modifichi le voci importate. L'importazione aggiunge voci; non aggiorna né elimina una transazione esistente. Effettua correzioni deliberatamente nel tuo libro mastro ed esegui bea check dopo. L'inserimento JSON in blocco con bea add transactions non ha rilevamento di duplicati.

5. Risolvi possibili duplicati​

Un download successivo può ripetere una riga con narrazione o ID bancari diversi. Data, beneficiario normalizzato e importo di origine firmato indicano ancora una possibile corrispondenza:

Stato anteprimaSignificatoCosa fare
newNessuna prova di duplicato trovataControlla importi e categorie
duplicateUn ID stabile e dettagli della transazione corrispondono, o esiste una direttiva non transazionale identicaGià saltato
possible_duplicateLa data, il beneficiario normalizzato e l'importo/valuta di origine firmati corrispondonoConfronta l'anteprima con la voce esistente
conflictUn ID stabile corrisponde a dettagli della transazione differentiRisolvi la discrepanza tra ID o dati, poi visualizza di nuovo l'anteprima

Un ID bancario diverso non esclude un duplicato. Le banche possono cambiare ID in download successivi. Anche due acquisti reali possono condividere data, beneficiario e importo, quindi una possibile corrispondenza è evidenza e non prova. Bea non fa supposizioni con un modello AI e non categorizza mai al posto tuo oltre le tue regole.

Il --duplicates review predefinito si rifiuta di applicare corrispondenze non risolte. In una verifica, un secondo file che ripete la riga 2026-08-02 Whole Foods -20.00 USD sotto una narrazione diversa è stato visualizzato come 1 possibile duplicato, e --apply è uscito 4 senza scrivere nulla. Dopo aver esaminato ogni possibile corrispondenza, scegli una di queste alternative:

bea --file books/main.bean import statement.csv --apply --duplicates skip
bea --file books/main.bean import statement.csv --apply --duplicates include

Scegli include per preservare acquisti ripetuti legittimi. La decisione si applica a tutte le possibili corrispondenze in quella esecuzione. I duplicati esatti rimangono saltati. I conflitti di ID bloccano ancora la scrittura. --no-input e --yes non bypassano questa revisione. Una decisione intenzionale di saltare ogni riga esce 0 senza aggiunte al libro mastro.

6. Usa un importatore Python per altri formati​

Per formati che la mappatura delle colonne non può esprimere, come OFX o QIF o un CSV con un layout insolito, bea import chiama un importatore configurato usando l'interfaccia corrente di Beangulp: identify(filepath), account(filepath) e extract(filepath, existing). L'importatore gestisce il parsing e la categorizzazione specifici della banca. Deve fornire importi espliciti nelle registrazioni del conto sorgente affinché il confronto dei duplicati usi gli importi reali della banca. Un importatore Python resta la via avanzata per questi formati. Per un CSV nativo di una banca, prova prima --csv.

Per una prima prova pratica, salva la configurazione di esempio CSV categorizzata come importers.py accanto al tuo libro mastro radice. Usa solo Beancount e la libreria standard di Python, quindi funziona con l'installazione Homebrew. Il suo bank.csv di esempio usa un importo segnato di un conto corrente: una spesa -5.25 USD per ristoranti e un deposito 1,000 USD da stipendio. La configurazione di esempio si aspetta esattamente le colonne documentate. Esegui solo configurazioni Python di cui ti fidi.

bea --file books/main.bean import bank.csv --config importers.py
bea --file books/main.bean import bank.csv --config importers.py --importer categorized-checking
bea --file books/main.bean import bank.csv --config importers.py --apply

La tua configurazione importers.py esporta CONFIG = [importer, ...]. Se diversi importatori riconoscono il file, seleziona uno per nome. Un nome sconosciuto elenca i nomi configurati. Un importatore noto che non riconosce il file lo segnala separatamente.

La CLI ricorda il percorso della configurazione per questo libro mastro radice. Le esecuzioni future scelgono l'esplicito --config, poi il percorso ricordato, poi importers.py accanto al radice. L'output indica il percorso e la sua origine.

--apply riesegue l'anteprima rispetto ai file correnti. Valida il libro mastro candidato completo prima di scrivere. Un errore di convalida lascia il libro mastro originale invariato ed esce con codice 1. Una modifica concorrente del libro mastro esce con codice 4; ispeziona la modifica e esegui una nuova anteprima prima di riprovare.

Mantieni gli import ripetibili​

Per impostazione predefinita, il controllo dei duplicati verifica i metadati bank_id, fitid, transaction_id e imported_id all'interno del conto di origine dell'importatore. Usa opzioni --id-key KEY ripetute per sostituire quel set.

Una riga con un ID bancario stabile viene scritta con metadati import-id che ne indicano il tipo, come un prefisso bank: o ofx:. Una riga senza tale ID viene scritta con un hash di contenuto csv:sha256: basato su data, importo, descrizione e conto, così che il re-import dello stesso file salta ogni riga. Le voci scritte prima di questa convenzione possono ancora contenere metadati bea_import_id e corrispondere anch'esse al re-import. Le possibili corrispondenze sono verificate rispetto a transazioni esistenti e alle righe accettate nello stesso batch.

Beneficiari, narrazioni e metadati stringa sostituiscono le interruzioni di riga con spazi prima dell'anteprima e della scrittura. Le virgolette e le barre rovesciate mantengono il loro contenuto. Il testo del commerciante importato rimane pertanto leggibile su una singola riga del libro mastro.

Scrivi in un file incluso​

Mantieni --file puntato alla radice e seleziona la destinazione con --into:

bea --file books/main.bean import statement.csv --into 2026.bean
bea --file books/main.bean import statement.csv --into 2026.bean --apply

2026.bean deve già esistere ed essere incluso dalla radice. Il suo percorso è relativo alla directory radice. Il percorso di esportazione rimane relativo alla tua directory di lavoro. L'anteprima individua il file che verrà modificato.

Usa gli import in uno script​

bea --file books/main.bean --json --no-input import statement.csv --apply --duplicates skip

Scegli skip solo quando questa è la tua politica prevista per le possibili corrispondenze. JSON restituisce l'anteprima e il conteggio di scrittura all'interno di data. Le richieste rifiutate mettono l'anteprima in error.result su stderr, con written: 0. Controlla sempre lo stato di uscita. Vedi la riferimento JSON e codice di uscita prima di programmare importazioni non assistite.

Risolvi i problemi di un importatore​

Le configurazioni degli importatori vengono eseguite nel motore gestito. Se una configurazione importa Beangulp, installa la libreria di sistema libmagic e abilita Beangulp lì una volta:

bea engine enable beangulp
bea --file books/main.bean import bank.ofx --config importers.py
bea --debug --file books/main.bean import bank.csv --config importers.py

bea engine status segnala le funzionalità abilitate. Installare un importatore bancario insieme al frontend bea non lo rende disponibile all'interno del motore. Una configurazione che importa pacchetti aggiuntivi necessita di quelle dipendenze nel motore; abilitare solo Beangulp non le installa. Usa il mappatore CSV o i convertitori qui sotto quando quelle dipendenze degli importatori non sono disponibili.

Per un'eccezione dell'importatore, posiziona --debug prima del comando per mostrare il traceback. L'output dell'importatore viene catturato in importer_output in modo da non corrompere il JSON. In modalità debug JSON, il traceback è error.traceback.

Per una conversione una tantum senza un importatore Python, prova il convertitore CSV o il convertitore OFX e QIF. Controlla le voci generate prima di aggiungerle ai tuoi registri.

Fonte: https://beancount.io/it/docs/Solutions/import-bank-exports-cli