Към основното съдържание

Автоматизирайте счетоводството с bea

Скриптирайте вашите Beancount книги с bea: разрешете ledger-а изрично, анализирайте JSON обвивката с jq, разклонявайте се по exit кодове, стартирайте без наблюдение и планирайте нощна проверка.

Скрипт управлява bea с четири решения: кой ledger чете, --json за машинно четим изход, jq за стойността, от която се нуждае, и exit кода, по който се разклонява. Това ръководство преминава през тези четири решения от край до край, след което ги планира.

Нуждаете се от bea на машината, която изпълнява задачата, и от ledger, до който може да достигне. Ако започвате нови книги, следвайте CLI бърз старт първо. Всеки факт за флагове, ключове на обвивката и exit кодове се проверява в Beancount CLI референтното ръководство, а не се повтаря тук.

Изберете ledger-а изрично​

Посочете файла. Локална команда разрешава своята цел от --file, след това от $BEA_FILE, след това от ./main.bean в работната директория, и планирана задача рядко се изпълнява там, където мислите.

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

Глобалните опции отиват преди командата, както в bea --file main.bean check. Ако разрешеният файл не съществува, командата излиза с код 2 и изброява и трите източника, така че печатна грешка в cron запис се проваля шумно вместо да валидира грешните книги. Хостирано насочване чрез флаг --ledger все още не съществува; bea никога не качва локален файл имплицитно.

Прочетете JSON обвивката​

Добавете глобален --json и всяка поддържана команда отговаря със същата обвивка: bea, target, data, truncated и limit върху ограничени списъци. Сумите са десетични низове, а датите са ISO YYYY-MM-DD, така че стойност е безопасна за сравнение, без float някога да влезе в тръбопровода. Ключовете на обвивката са таблицирани в JSON и exit код референтното ръководство.

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}'

Тези три команди — report, list и import — запазват своите резултатни форми, така че jq път, написан срещу тях, остава валиден. bea --json check и bea --json query също издават обвивката днес, но те са командите, които се предават на нативните Beancount изпълними файлове, така че скрипт трябва да разчита на check-овия exit статус, а не на неговата изходна форма. Изберете вашата политика за дубликати умишлено: --duplicates все още е задължително, когато импорт се нуждае от решение, както обяснява walkthrough за импорт.

Спрете на правилния exit код​

Разклонявайте се по статуса и прочетете обекта за грешка преди повторен опит на нещо, което записва. В --json режим неуспех не записва нищо на stdout и точно един обект на stderr, чийто error.category назовава класа: 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 е този, по който скрипт никога не трябва да повтаря сляпо: това означава, че резултатът е конфликт или е неизвестен, като външна редакция, пристигаща по средата на запис, или init цел, която вече съществува. Инспектирайте ledger-а, след това повторете от свежо четене. Exit 1 покрива грешки при валидация и всяка друга грешка по време на изпълнение; error.details носи индивидуалните грешки на ledger-а, а error.result носи това, което частичен запис всъщност е направил. Ненулев exit никога не гарантира, че нищо не се е променило.

Работете без терминал​

bea спира да подканва сам. --no-input се подразбира винаги, когато stdin не е терминал, винаги, когато --json е зададен, и винаги, когато CI е истинен — 1, true, yes или on. В този режим липсващо потвърждение се проваля с exit 2 вместо да чака вечно.

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

Четенията са снизходителни в терминал и строги навсякъде другаде. Когато ledger-ът има грешки при зареждане, query, list и report излизат с 1 под --json, под тръбен stdout, под истинен CI или с --strict; предайте собствената --allow-errors опция на командата, за да приемете частичния отговор вместо това, което също задава ledger_valid: false и попълва ledger_errors в JSON-а. --strict е огледален образ: отказва частични отговори дори в терминал, което е това, което искате, когато човек изпълнява същия скрипт на ръка. bea check няма --allow-errors — докладването на грешки е цялата му работа — и винаги излиза с 1, когато намери такива. Задайте BEA_NO_UPDATE_NOTIFIER=1, за да заглушите пасивното известие за актуализация; истинен CI вече го прави.

Планирайте проверка​

Изпълнявайте валидация всяка нощ и оставете exit кода да бъде предупреждението. И двата блока по-долу са шаблони — пътищата, графикът и изпълнителят са ваши.

# 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

Първата команда, задвижвана от двигател, изтегля управлявания двигател, така че изпълнителят се нуждае от мрежов достъп. За повторна употреба между задачи, кеширайте ~/.local/share/bea/engine с ключ, съдържащ ОС на изпълнителя, архитектура, Python версия и фиксирана bea версия. Фиксирайте версията, когато задачата трябва да бъде възпроизводима, и премахнете фиксирането, когато предпочитате да следите изданията. CI вече е истинен на GitHub Actions, така че подканите са изключени и известието за актуализация е тихо, преди да зададете каквото и да било. Няма стъпка за форматиране тук умишлено. Планирана задача не трябва да пренаписва файлове, които не е трябвало, така че използвайте bea format main.bean --check в pre-commit кука, която не докосва нищо и излиза с 1, когато файл се нуждае от форматиране.

Използвайте хоствано удостоверение в задача​

Задайте BEA_TOKEN, от хранилището за тайни на вашия CI доставчик, и пропуснете вход в браузъра изцяло. Токенът се чете от средата и никога не се записва на диск, така че нищо не попада в домашната директория на изпълнителя за следващата задача да намери.

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

Exit 0 означава, че удостоверението е разрешено и обвивката назовава акаунта, към който принадлежи; exit 3 с error.category от auth означава, че не е, и съобщението разграничава незададено удостоверение от отхвърлено. bea cloud logout не прави нищо на токен, предоставен по този начин — нито го отменя, нито го премахва, тъй като друга задача може да го споделя — така че отменете изтекъл токен от таблото вместо това. Локалните команди не се нуждаят от никакво удостоверение; само bea cloud и bea ask достигат до хостваната услуга. Пълният списък с променливи е в референтното ръководство за настройки.

Не всичко отговаря в JSON. bea ask отхвърля JSON режима напълно, bea cloud login се нуждае от човек, и успешен bea cloud logout или bea cloud ledger clone не връща JSON обект за успех — прочетете техния exit статус вместо това. Помощта, версията и изходът за допълване на команди остават текстови.

Следващи стъпки​

Източник: https://beancount.io/bg/docs/Solutions/automate-bookkeeping-with-bea