hledger/bin/justfile

275 lines
10 KiB
Makefile
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env just -f
# * financial reports/scripts, runnable with https://github.com/casey/just
# (like make but simpler and more suitable for running commands.)
# ** PREAMBLE ------------------------------------------------------------
# XXX we don't quote HLEDGERARGS properly, so each one must be free of spaces
just := "just -f " + justfile()
# list the commands available
@help:
{{just}} -lu --list-heading=$'{{ file_name(justfile()) }} commands:\n\
HLEDGERARGS can be added to customise reports.\n\
NOTCHOOSABLE is a required dummy argument, write - for it. Eg: just browse -\n\
'
# interactively pick a command with the default chooser. Eg: just pick -
pick NOTCHOOSABLE:
{{just}} --choose
# interactively view command outputs with fzf and bkt. Eg: just view - --black
view NOTCHOOSABLE *FZFARGS:
{{just}} --choose --chooser="fzf --reverse --preview='bkt --ttl=15m --stale=15s -- just {}' {{FZFARGS}}"
# rerun the given command with watchexec whenever local files change
watch CMD:
watchexec -- {{just}} {{CMD}}
# ** IMPORT ------------------------------------------------------------
TODAY := `date +%Y-%m-%d`
# where to import most hledger transactions from
IMPORTFILES := '\
wf-bchecking.csv.rules \
wf-pchecking.csv.rules \
wf-bsavings.csv.rules \
wf-psavings.csv.rules \
paypal.csv \
bofi-ichecking.csv.rules \
'
# download auto-downloadable CSVs (paypal)
@get-csv NOTCHOOSABLE:
paypaljson | paypaljson2csv > paypal.csv
# import new downloaded transactions to the main journal, dry run
@import-dry:
hledger import --dry-run {{IMPORTFILES}}
# import new downloaded transactions to the journal, logging and not printing errors
@import NOTCHOOSABLE:
date >>import.log
@hledger import {{IMPORTFILES}} 2>>import.log || echo "Failed, check import.log"
echo "Now use ledger-mode's M-q to align entries."
# show prices for main commodities (default: today's)
@get-prices NOTCHOOSABLE *PRICEHISTFETCHOPTS :
(pricehist fetch -o ledger -s {{TODAY}} alphavantage EUR/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/EUR/€/') &
(pricehist fetch -o ledger -s {{TODAY}} alphavantage GBP/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/GBP/£/') &
(pricehist fetch -o ledger -s {{TODAY}} alphavantage JPY/USD {{PRICEHISTFETCHOPTS}} | sed -E 's/JPY/¥/')
# Parallelised for speed; do slowest last.
# Output order varies, can be sorted with LC_COLLATE=C.UTF-8 sort or hledger -f- prices.
# ** REPORTS ------------------------------------------------------------
PERIOD := "1/1..tomorrow"
# show balance sheet
bs *HLEDGERARGS :
hledger bs --layout bare --pretty --drop 1 -p {{PERIOD}} -E -5 {{HLEDGERARGS}}
# show income statement
is *HLEDGERARGS :
hledger is --layout bare --pretty --drop 1 -p {{PERIOD}} -S {{HLEDGERARGS}}
# show assets
a *HLEDGERARGS :
hledger bal type:al -H --layout bare --pretty --drop 1 -p {{PERIOD}} -E {{HLEDGERARGS}}
# show revenues
r *HLEDGERARGS :
hledger bal type:r --layout bare --pretty --drop 1 -p {{PERIOD}} -S --invert {{HLEDGERARGS}}
# show expenses
x *HLEDGERARGS :
hledger bal type:x --layout bare --pretty --drop 1 -p {{PERIOD}} -S --invert {{HLEDGERARGS}}
# show assets bar chart
ab *HLEDGERARGS :
echo "Quarterly net worth:"
hledger-bar -v 200 -Q type:al -H {{HLEDGERARGS}}
# show revenues bar chart
rb *HLEDGERARGS :
echo "Quarterly revenues:"
hledger-bar -v 40 -Q type:r --invert {{HLEDGERARGS}}
# show expenses bar chart
xb *HLEDGERARGS :
echo "Quarterly expenses:"
hledger-bar -v 40 -Q type:x --invert {{HLEDGERARGS}}
# XXX with partial workaround for https://github.com/gooofy/drawilleplot/issues/4
# show assets line chart
al *HLEDGERARGS :
hledger plot -- bal --depth=1 type:a --historical --terminal --rcParams '{"figure.figsize":[8,3]}' --no-today -q --title "hledger assets" {{HLEDGERARGS}} | sed 's// /g'
# show revenues line chart
rl *HLEDGERARGS :
hledger plot -- bal --depth=1 type:r --monthly --invert --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly revenues" {{HLEDGERARGS}} | sed 's// /g'
# show expenses line chart
xl *HLEDGERARGS :
hledger plot -- bal --depth=1 type:x --monthly --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly expenses" {{HLEDGERARGS}} | sed 's// /g'
# print transactions predicted by forecast rules from last week on
forecast *HLEDGERARGS :
hledger print --auto --forecast=lastweek.. -I tag:_generated {{HLEDGERARGS}}
# show a draft month-end household adjustment transaction for last month
household *HLEDGERARGS :
env household "$($date -v-1m +%b)"
# show consulting revenue
consulting *HLEDGERARGS :
hledger reg --invert 'revenues:(cw|ah)' -p {{PERIOD}} {{HLEDGERARGS}}
# estimated-tax *HLEDGERARGS :
# @echo "Federal estimated tax due for this year"
# $(HLEDGER) register liabilities:personal:tax:federal:$(YEAR) --width=130
# @echo State estimated tax due for this year:
# @$(HLEDGER) register liabilities:personal:tax:state:$(YEAR) --width=130
# @echo
# ** TIME REPORTS ------------------------------------------------------------
set export
# The file where actual time data is logged, for dashboard's stats.
# This might or might not be the top-level $TIMELOG file.
#TIMELOGDATA=$TIMELOG
YEAR := `date +%Y`
TIMELOGDATA := 'time-' + YEAR + '.timedot'
# This redisplays only when a file listed by `hledger -f $TIMELOG files` is modified.
# To force a per minute display as well, have $TIMELOG include a dummy file (.update)
# and configure a cron job to touch that every minute.
# (This is better than touching the timelog file itself, which confuses editors.)
#
# show time dashboard, redisplaying when timelog files change
tdash NOTCHOOSABLE *HLEDGERARGS:
#!/usr/bin/env bash
set -euo pipefail
dir=$(dirname "$TIMELOG")
cd "$dir"
opts= #--poll=10 # <- uncomment to fix symlinked files being ignored
watchexec $opts --no-vcs-ignore \
--filter-file=<(hledger -f "$TIMELOG" files | sed -E "s|$dir/||g") \
-c -r {{just}} tstatus {{HLEDGERARGS}}
# show time dashboard, redisplaying every minute with watch
# dash-1m *HLEDGERARGS:
# watch -n60 -c tt status
# }
# show current time status
tstatus *HLEDGERARGS:
#!/usr/bin/env bash
set -euo pipefail
date=$(if [ "$(builtin type -p gdate)" ]; then echo gdate; else echo date; fi)
stat=$(if [ "$(builtin type -p gstat)" ]; then echo gstat; else echo stat; fi)
curtime=$($date +'%H:%M %Z, %a %b %-e %Y')
modtime=$($date +'%H:%M %Z' -r "$TIMELOGDATA")
modsecs=$($stat -c %Y "$TIMELOGDATA")
nowsecs=$($date +%s)
agesecs=$((nowsecs - modsecs))
agemins=$(python3 -c "print($agesecs/60)")
agehrs=$(python3 -c "print($agesecs/3600.0)")
ageqtrhrs=$(python3 -c "print(round($agesecs/900.0))")
agedots=$({{just}} tdots "$ageqtrhrs")
printf "Current time: %s\n" "$curtime"
# old, for osh: use env here to run the system printf, which supports floating point
env printf "Timelog saved: %s, %.0fm / %.1fh / %s ago\n" "$modtime" "$agemins" "$agehrs" "$agedots"
# Show the current day/week/month budget status.
printf "Time plans:\n"
# calculate each period's budget from daily budget
hledger -f "$TIMELOG" bal -1 -p 'daily today' --budget=Daily {{HLEDGERARGS}} | tail +2
hledger -f "$TIMELOG" bal -1 -p 'weekly this week' --budget=Daily {{HLEDGERARGS}} | tail +2
hledger -f "$TIMELOG" bal -1 -p 'monthly this month' --budget=Daily {{HLEDGERARGS}} | tail +2
# or use each period's specific budget
# hledger -f "$TIMELOG" bal -p 'daily today' --budget=Daily -1 | tail +2
# hledger -f "$TIMELOG" bal -p 'weekly this week' --budget=Weekly -1 | tail +2
# hledger -f "$TIMELOG" bal -p 'monthly this month' --budget=Monthly -1 | tail +2
echo
hledger -f "$TIMELOG" check -s tags ordereddates || true
# this comes last because it's slow and variable length
echo
printf "Display activity:\n"
wakelog today | tail -n 6
# what happened ? Show largest time balances first, today and depth 1 by default
@twhat *HLEDGERARGS:
hledger -f "$TIMELOG" bal -S -1 -p today {{HLEDGERARGS}}
# print line of N dots, grouped in 4s (suitable for timedot)
tdots N:
#!/usr/bin/env bash
set -euo pipefail
n={{N}}
ndiv4=$((n/4))
nmod4=$((n-n/4*4))
sep=''
while [[ $ndiv4 -gt 0 ]]; do ndiv4=$((ndiv4-1)); echo -n "$sep...."; sep=' '; done
while [[ $nmod4 -gt 0 ]]; do nmod4=$((nmod4-1)); echo -n "$sep."; sep=''; done
echo
RFLAGS:='-tM' #TA
# horizontal time summary this year, monthly by default
@tx *HLEDGERARGS:
hledger -f "$TIMELOG" bal -1 "$RFLAGS" {{HLEDGERARGS}}
# vertical time summary this year, monthly by default
@ty *HLEDGERARGS:
hledger -f "$TIMELOG" bal -1 "$RFLAGS" --transpose {{HLEDGERARGS}}
# this and last week's time budgets
@tweeks *HLEDGERARGS:
printf "\nLast week, this week:\n"
timeweekly run
# recent past weeks' time budgets
@tweekspast *HLEDGERARGS:
printf "\nPast weeks:\n"
timeweekly past
# show a bar chart of daily hours
@thours *HLEDGERARGS:
hledger-bar -v 1 -f "$TIMELOG" -D {{HLEDGERARGS}}
# show unused / undeclared time accounts
@taccunused *HLEDGERARGS:
echo "Unused: (but declared)"
hledger -f "$TIMELOG" acc --unused {{HLEDGERARGS}} --directives | gsed -E 's/:(.)/.\1/g'
echo
echo "Undeclared: (but used)"
hledger -f "$TIMELOG" acc --undeclared {{HLEDGERARGS}} --directives | gsed -E 's/:(.)/.\1/g'
# show unused / undeclared time accounts by category
@taccunusedcat *HLEDGERARGS:
for a in $(tt acc -1); do line; echo "$a":; tt unused "^$a"; echo; done; line
# add declarations for all undeclared time accounts
@taccadd *HLEDGERARGS:
hledger -f "$TIMELOG" accounts --undeclared --directives | sed 's/:/./g' >>"$TIMELOG"
# show monthly time budget performance this year
@tbudgets *HLEDGERARGS:
{{just}} tx --budget=daily -M -p jan..tomorrow {{HLEDGERARGS}}
# show monthly time budget performance this year, vertically
@tbudgetsy *HLEDGERARGS:
{{just}} ty --budget=daily -M -p jan..tomorrow {{HLEDGERARGS}}
# dedicated weekly reports, needed to set proper week start date, to ensure simple headings:
# show weekly time budget performance this year
@tbudgetsw *HLEDGERARGS:
{{just}} ty --budget=daily -W -p 3/27..tomorrow {{HLEDGERARGS}}
# show weekly time budget performance this year, horizontally
@tbudgetswx *HLEDGERARGS:
{{just}} tx --budget=daily -W -p 3/27..tomorrow {{HLEDGERARGS}}