Recipes
Short recipes for questions people ask their books. They use jq to process JSON. Replace the example IDs with your own.
Overdue receivables by customer#
fob-zb invoices list --status overdue --format json \
| jq -r '.invoices | group_by(.customer_name)
| map({customer: .[0].customer_name, overdue: (map(.balance) | add)})
| sort_by(-.overdue)[] | "\(.overdue)\t\(.customer)"'
Bills due this week#
List commands have no date filter, so filter by date with jq:
fob-zb bills list --status open --format json \
| jq -r --arg until "$(date -v+7d +%F 2>/dev/null || date -d '+7 days' +%F)" \
'.bills[] | select(.due_date <= $until) | [.due_date, .vendor_name, .balance] | @tsv'
Export the chart of accounts#
fob-zb chart-of-accounts list --format csv \
--fields account_code,account_name,account_type,parent_account_name,is_active \
--output chart-of-accounts.csv
Uncategorized bank transactions per account#
fob-zb bank-accounts list --fields account_name,balance,uncategorized_transactions
Then work through one account's feed:
fob-zb bank-transactions list --account-id 4600xxxxxxx --status uncategorized \
--fields transaction_id,date,amount,debit_or_credit,payee,reference_number
Customers with the largest outstanding balance#
fob-zb contacts list --type customer --format json \
| jq -r '.contacts | sort_by(-.outstanding_receivable_amount) | .[:10][]
| "\(.outstanding_receivable_amount)\t\(.contact_name)"'
The same report for every organization#
for p in $(fob-zb config profiles list --json | jq -r '.profiles[].name'); do
echo "== $p"
fob-zb invoices list --status overdue --profile "$p" --fields invoice_number,customer_name,balance
done
Record payments from a CSV#
Given payments.csv with the columns vendor_id,bill_id,amount,date:
tail -n +2 payments.csv | while IFS=, read -r vendor bill amount date; do
fob-zb vendor-payments create --vendor "$vendor" --bill "$bill" --amount "$amount" \
--date "$date" --paid-through 4600bbbbbbb --profile test
done
Run it against --profile test first, then switch to your real profile.