Preskočiť na hlavný obsah

Automatizujte účtovníctvo s bea

Skriptujte svoje Beancount účtovné knihy s bea: vyriešte hlavnú knihu explicitne, parsujte JSON obálku s jq, vetvite na exit kódy, spúšťajte bez dozoru a naplánujte nočnú kontrolu.

Skript riadi bea pomocou štyroch rozhodnutí: ktorý ledger číta, --json pre strojovo čitateľný výstup, jq pre potrebnú hodnotu a ukončovací kód, podľa ktorého sa vetví. Tento návod prechádza týchto štyri rozhodnutí od začiatku do konca, potom ich plánuje.

Na stroji, ktorý spúšťa úlohu, potrebujete bea a ledger, ku ktorému má prístup. Ak začínate nové knihy, najprv postupujte podľa rýchleho štartu CLI. Všetky fakty o príznakoch, kľúčoch obálok a ukončovacích kódoch sú vyhľadávané v Beancount CLI reference a tu sa nezopakujú.

Vyberte ledger explicitne​

Pomenujte súbor. Lokálny príkaz vyrieši jeho cieľ v poradí --file, potom $BEA_FILE, potom ./main.bean v pracovnom adresári, a plánovaná úloha zriedka beží tam, kde si myslíte.

bea --file ~/books/main.bean check
BEA_FILE=~/books/main.bean bea check
cd ~/books && bea check

Globálne možnosti idú pred príkaz, ako v bea --file main.bean check. Ak vyriešený súbor neexistuje, príkaz skončí s 2 a zobrazí všetky tri zdroje, takže chyba v zápise cron-u zlyhá hlasno namiesto overenia nesprávnych kníh. Zatiaľ neexistuje hosťované zacieľovanie cez príznak --ledger; bea nikdy implicitne neodosiela lokálny súbor.

Prečítajte JSON obálku​

Pridajte globálny --json a každý podporovaný príkaz odpovedá tou istou obálkou: bea, target, data, truncated a limit na obmedzených zoznamoch. Suma je decimálny reťazec a dátumy sú vo formáte ISO YYYY-MM-DD, takže hodnota je bezpečná na porovnávanie bez toho, aby sa do procesu dostala float. Kľúče obálky sú uvedené v tabuľke v odkaze na JSON a ukončovacie kódy.

bea --json --file main.bean report income-statement | jq .data.net_profit
bea --json --file main.bean list transaction --limit 2 | jq '.data[0].postings[0].units'
bea --json --file main.bean import statement.csv --csv date=Date,amount=Amount,payee=Payee \
  --account Assets:Checking --apply --duplicates skip | jq '.data | {written, ready, duplicates}'

Tieto tri príkazy — report, list a import — si zachovávajú svoj tvar výsledku, takže cesta jq napísaná proti nim zostáva platná. bea --json check a bea --json query dnes tiež emitujú obálku, ale sú to príkazy odovzdané natívnym Beancount spustiteľným súborom, takže skript by mal stavať na ukončovacom stave check namiesto tvaru jeho výstupu. Vyberte svoju politiku duplicit podľa zámeru: --duplicates je stále potrebný, keď import potrebuje rozhodnutie, ako vysvetľuje návod na import.

Zastavte sa na správnom ukončovacom kóde​

Vetvite podľa stavu a pred opakovaním čítajte chybový objekt pred čímkoľvek, čo zapisuje. V režime --json porucha nič nezapisuje na stdout a presne jeden objekt na stderr, ktorého error.category určuje triedu: validation (1), usage (2), auth (3), conflict (4).

#!/usr/bin/env bash
set -euo pipefail
 
out=$(mktemp)
err=$(mktemp)
status=0
 
bea --json --file main.bean report income-statement >"$out" 2>"$err" || status=$?
 
case "$status" in
  0) jq -r '.data.net_profit | to_entries[] | "net profit: \(.value) \(.key)"' "$out" ;;
  4) echo "conflict — inspect the ledger before retrying" >&2
     jq -r '.error.message' "$err" >&2
     exit 4 ;;
  *) jq -r '.error | "\(.category) (exit \(.exit_code)): \(.message)"' "$err" >&2
     exit "$status" ;;
esac

Exit 4 je stav, ktorý skript nesmie nikdy znovu pokúšať bez rozmyslu: znamená, že výsledok je konflikt alebo neznámy, napríklad externá úprava prichádzajúca počas zápisu alebo cieľ init, ktorý už existuje. Skontrolujte knihu zápisov a potom skúste znova načítať z čerstvého čítania. Exit 1 pokrýva zlyhania overenia a akúkoľvek inú runtime chybu; error.details nesie jednotlivé chyby v knihe zápisov a error.result nesie, čo čiastočný zápis vlastne vykonal. Ne-nulový exit nikdy nezaručuje, že sa nič nezmenilo.

Spustenie bez terminálu​

bea sám od seba prestáva vyžadovať zadanie. --no-input sa implikuje vždy, keď stdin nie je terminál, vždy keď je nastavený --json a vždy keď je pravdivý CI — 1, true, yes alebo on. V tomto režime chýbajúce potvrdenie zlyhá výstupom 2 namiesto nekonečného čakania.

CI=true BEA_NO_UPDATE_NOTIFIER=1 bea --json --file main.bean report balance-sheet
bea --json --file main.bean list transaction --limit 100 --sort oldest

Čítanie je v termináli tolerantné a inde prísne. Keď má kniha zápisov chyby načítania, query, list a report ukončia 1 pod --json, pod preposlaným stdout, pod pravdivým CI alebo s --strict; použite vlastný --allow-errors príkazu, aby ste namiesto toho akceptovali čiastočnú odpoveď, čo tiež nastavuje ledger_valid: false a vyplňuje ledger_errors v JSON-e. --strict je zrkadlový obraz: odmieta čiastočné odpovede aj v termináli, čo je to, čo chcete, keď človek spúšťa rovnaký skript ručne. bea check nemá --allow-errors — hlásenie chýb je jeho celou úlohou — a vždy končí 1, keď nájde nejaké chyby. Nastavte BEA_NO_UPDATE_NOTIFIER=1 na stlmenie neaktívneho upozornenia na aktualizáciu; pravdivý CI to už robí.

Naplánovať kontrolu​

Spustite validáciu každú noc a nechajte návratový kód byť upozornením. Obe nižšie uvedené bloky sú šablóny — cesty, plán a spúšťač sú vaše.

# crontab -e — 07:15 daily; cron mails you only when bea exits nonzero
15 7 * * * BEA_NO_UPDATE_NOTIFIER=1 /opt/homebrew/bin/bea --file /home/alice/books/main.bean check
name: ledger
on:
  schedule:
    - cron: "15 7 * * *"
  push:
jobs:
  check:
    runs-on: ubuntu-latest
    env:
      BEA_NO_UPDATE_NOTIFIER: "1"
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5
      - run: uv tool install beancount-io==0.2.0
      - run: bea --file main.bean check
      - run: bea --json --file main.bean report balance-sheet > balance-sheet.json

Prvý príkaz založený na engine stiahne spravovaný engine, takže spúšťač potrebuje prístup na sieť. Na opakované použitie medzi úlohami uložte ~/.local/share/bea/engine do vyrovnávacej pamäte s kľúčom obsahujúcim OS spúšťača, architektúru, verziu Pythonu a pripnutú verziu bea. Pripnite verziu, keď musí byť úloha reprodukovateľná, a uvoľnite pripnutie, keď radšej sledujete vydania. CI je už pravdivý na GitHub Actions, takže výzvy sú vypnuté a upozornenie na aktualizáciu je tiché, než niečo nastavíte. Tu účelne nie je žiadny formátovací krok. Naplánovaná úloha by nemala prepísať súbory, ktoré nemusela, preto siahnite po bea format main.bean --check v pred-commit hooku, ktorý sa ničho nedotýka a končí 1, keď je potrebné formátovanie súboru.

Použitie hostovanej poverovacej informácie v úlohe​

Nastavte BEA_TOKEN z úložiska tajomstiev vášho poskytovateľa CI a úplne preskočte prihlasovanie cez prehliadač. Token sa načítava z prostredia a nikdy sa nezapisuje na disk, takže nič neskončí v domovskom adresári runnera, aby ho našla nasledujúca úloha.

export BEA_TOKEN="$YOUR_CI_SECRET"
bea --json cloud status

Exit 0 znamená, že poverenie bolo vyriešené a obálka určuje účet, ku ktorému patrí; exit 3 s error.category z auth znamená, že nie je vyriešené, a správa rozlišuje nenastavené poverenie od zamietnutého. bea cloud logout nič nerobí s tokenom poskytnutým týmto spôsobom — ani ho nezruší, ani nenastaví na nulovú hodnotu, pretože môže byť zdieľaný s inou úlohou — preto radšej zrušte uniknutý token z dashboardu. Lokálne príkazy nepotrebujú žiadne poverenia, len bea cloud a bea ask sa pripájajú k hosťovanej službe. Kompletný zoznam premenných je v referencii nastavení.

Nie všetko odpovedá v JSON. bea ask kategóricky odmieta režim JSON, bea cloud login vyžaduje človeka a úspešný bea cloud logout alebo bea cloud ledger clone nevracia žiadny objekt JSON úspechu — namiesto toho čítajte ich návratový stav. Výstupy help, version a shell-completion zostávajú textové.

Ďalšie kroky​

Zdroj: https://beancount.io/sk/docs/Solutions/automate-bookkeeping-with-bea