diff --git a/bin/csv.mk b/bin/csv.mk deleted file mode 100644 index 565f40909..000000000 --- a/bin/csv.mk +++ /dev/null @@ -1,38 +0,0 @@ -# some CSV-related make scripts - -HLEDGER=hledger - -YEAR:=$(shell date +%Y) -MONTH:=$(shell date +%m) -MONTHS:=$(shell ghc -e "(putStr . unwords . map show) [1..$(MONTH)]") -MONTHS2:=$(shell ghc -e "(putStr . unwords . map show) [2..$(MONTH)]") - -############################################################################### - -# convert latest bank csv downloads to journal files -BANKJOURNALS = \ - mint.journal \ - WellsFargoChecking1.journal \ - WellsFargoSavings2.journal \ - WellsFargoSavings3.journal \ - WellsFargoCreditCard4.journal \ - Paypal.journal -convert-csv: move-csv $(BANKJOURNALS) - -# move and rename any newly downloaded bank csv files -DOWNLOADDIR=~/Desktop -move-csv: - @(F=$(DOWNLOADDIR)/transactions.csv; [ -e $$F ] && (mv $$F mint.csv; echo new mint.csv found) || exit 0) - @(F=$(DOWNLOADDIR)/Checking1.csv; [ -e $$F ] && (mv $$F WellsFargoChecking1.csv; echo new WellsFargoChecking1.csv found) || exit 0) - @(F=$(DOWNLOADDIR)/Savings2.csv; [ -e $$F ] && (mv $$F WellsFargoSavings2.csv; echo new WellsFargoSavings2.csv found) || exit 0) - @(F=$(DOWNLOADDIR)/Savings3.csv; [ -e $$F ] && (mv $$F WellsFargoSavings3.csv; echo new WellsFargoSavings3.csv found) || exit 0) - @(F=$(DOWNLOADDIR)/CreditCard4.csv; [ -e $$F ] && (mv $$F WellsFargoCreditCard4.csv; echo new WellsFargoCreditCard4.csv found) || exit 0) - @(F=$(DOWNLOADDIR)/Download.csv; [ -e $$F ] && (mv $$F Paypal.csv; echo new Paypal.csv found) || exit 0) - -# convert a csv to a journal using the similarly named rules file -%.journal: %.csv %.rules - $(HLEDGER) convert $< >$@ - -%.rules: - touch '$@' - diff --git a/examples/csv/Makefile b/examples/csv/Makefile new file mode 100644 index 000000000..9e2f23d75 --- /dev/null +++ b/examples/csv/Makefile @@ -0,0 +1,126 @@ +# * Finance makefile -*- mode:makefile-gmake; eval:(outshine-mode 1); -*- +# ** ABOUT +# This makefile, based on SM's circa 2023, is a place to keep small finance-related scripts. +# In particular, it is responsible for collecting and importing downloaded CSV files +# (which is why it is in the examples/csv/ folder, even though not only useful for CSV). +# It handles the tedious file management and importing. Hopefully more of this +# will be done by hledger some day. +# +# To list available targets: make or make help-PAT +# To debug a target: make SHELL='sh -x' [-n] TARGET +# When logic or quoting or syntax gets hard: use shell scripts in bin/ instead. + +# -*- -*- sets modes in Emacs. outshine mode treats "# *" as outline headings, cycleable with TAB. + +# ensure failure in piped commands causes make to fail. Good for some but not others. +#SHELL=sh -o pipefail + +YEAR:=$(shell date +%Y) +JOURNAL=$(YEAR).journal +HLEDGER=hledger +RG=rg -IN --sort=path + +help: # list make targets + @printf "Targets:\n" + @$(RG) '^# \*\* (.*)|^(\w[^:]*):($$| [^#]*(# [^#]*)?$$)' -or '$$1 $$2|$$4' $(MAKEFILE_LIST) | column -t -s'|' || true +# Shows second level outshine headings and targets beginning with a word character and not followed by a ## same-line comment. + +help-%: # list make targets matching a pattern + @make -s help | $(RG) "$*" || true + +PHONY: ## Depend on this to make phony targets (more easily than .PHONY: foo bar baz..) + +############################################################################### +# ** DOWNLOAD + +# CSVs should be downloaded/exported manually to this directory. +# You should remove any old downloads first, so browsers don't save the new ones with a wrong name. +DOWNLOADDIR=~/Downloads + +init: # ensure all importable CSVs exist. Run this once at the start to keep make happy. + touch $(CSVS) + +# Keep the following three lists in sync. + +# 1. CSV files with standard names, from which we will import transactions. +CSVS=\ + wf-checking.csv \ + wf-savings.csv \ + paypal.csv \ + vanguard.csv \ +# stripe.csv \ +# stripeexpress.csv \ + +# 2. How to make these CSV files (what download file to copy them from). +wf-checking.csv: $(DOWNLOADDIR)/Checking1.csv ; mv $< $@ +wf-savings.csv: $(DOWNLOADDIR)/Savings2.csv ; mv $< $@ +paypal.csv: $(DOWNLOADDIR)/Download.csv ; mv $< $@ +vanguard.csv: $(DOWNLOADDIR)/ofxdownload.csv ; mv $< $@ +#stripe.csv: $(DOWNLOADDIR)/Itemized_balance_change_from_activity_USD_*.csv ; mv $< $@ +#stripeexpress.csv: $(DOWNLOADDIR)/StripeExpressActivity_*.csv ; mv $< $@ + +# 3. Marking them as intermediate files (https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html). +.INTERMEDIATE: \ + $(DOWNLOADDIR)/Checking1.csv \ + $(DOWNLOADDIR)/Savings2.csv \ + $(DOWNLOADDIR)/Download.csv \ + $(DOWNLOADDIR)/ofxdownload.csv \ +# $(DOWNLOADDIR)/Itemized_balance_change_from_activity_USD_*.csv \ +# $(DOWNLOADDIR)/StripeExpressActivity_*.csv \ + +csv: $(CSVS) # move any downloaded CSVs to the standard filenames above + +# paypal.csv: PHONY # download paypal CSV from API +# paypaljson | paypaljson2csv > $@ + +############################################################################### +# ** IMPORT + +# hledger .latest files used for remembering the csvs' import state +IMPORTLATESTFILES=$(CSVS:%=.latest.%) + +# hledger .rules files used for parsing the csvs +IMPORTRULESFILES=\ + $(CSVS:=.rules) \ + wf.rules \ + common.rules \ + +Import: csv import # move all downloaded CSVs here and import any new transactions to the journal + +import: # import any new transactions from CSV to the journal + @date >>import.log + hledger -f $(JOURNAL) import $(CSVS) 2>>import.log || echo "Failed, check import.log" +# Avoids showing hledger errors on stdout in case it is being called by cron and emailed. +# Logs to import.log. + +import-dry: # like import but just do a dry run, without changing the journal or import state + hledger -f $(JOURNAL) import --dry-run $(CSVS) + +import-dry-watch: # rerun import-dry as files change + watchexec -- make import-dry + +import-dry-unknowns: # like import-dry but show only the transactions that rules have not categorised + @hledger -f $(JOURNAL) import --dry-run $(CSVS) | hledger -f- -I print unknown + +import-dry-unknowns-watch: # rerun import-dry-unknowns as files change + watchexec -- make import-dry-unknowns + +############################################################################### +# ** PRICES + +PRICELOG=$(YEAR)prices.journal +MARKET_PRICES=~/src/PTA/hledger-scripts/market-prices/market-prices.py