diff --git a/README.md b/README.md index e138e76..7c46537 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ handle the same use-case. I have tried a couple of them, as well as the integrated CSV import of hledger, and ran into issues with all of them. That's why I wrote yet another CSV to ledger tool. -There are two scripts, getofx, and toldg. The former uses the Python +There are two main scripts, getofx, and toldg. The former uses the Python [ofxtools](https://ofxtools.readthedocs.io/en/latest/) library to download bank -transactions via OFX and stores them into CSV files. The latter takes CSV files +transactions via OFX and stores them into CSV files. The latter takes CSV files and transforms them into ledger accounting files. The OFX script works well for my workflow, but I am not sure if it would be @@ -31,6 +31,12 @@ my workflows are editor based, and the mapping file-based approach makes it easy to manipulate transactions. Also, the script relies on a single configuration file, which makes the configuration clearer. +The directory `tools` contains additional scripts for personal use. Currently +their main use-case is to generate a PDF report with figures. I use hledger to +generate CSV data, plot figures with pandas, and then generate a report with +pandoc. A shell script executes this process. This workflow fulfills my +requirements, but is currently not useful for anybody else. + ## Dependencies The scripts rely on a couple of newer Python features, such as data-classes, @@ -84,4 +90,5 @@ getting warnings. - [x] Use OFX parser from ofxtools instead of parsing the XML - [x] Autoappend latest OFX data to CSV file - [x] Include example workspace with mock data to demo my workflow +- [x] Write script to generate PDF reports diff --git a/report.py b/report.py deleted file mode 100644 index 0100a37..0000000 --- a/report.py +++ /dev/null @@ -1,32 +0,0 @@ -import subprocess -import numpy as np -import matplotlib.pyplot as plt -import pandas as pd - -def configure_plot(): - plt.figure() - axes = plt.gca() - axes.set_xlim([0, 300]) - axes.set_ylim([-256, 100]) - plt.xlabel("#bets []") - plt.ylabel("win [$]") - -def report(): - df = pd.read_csv("report.csv", - index_col='Account', - parse_dates=True) - df = df.drop(columns="Total:") - #print(df) - # print(df.info()) - df.plot.bar() - plt.savefig('figure_1.png') - # plt.show() - - -if __name__ == "__main__": - c = "hledger balance -M -V -b 2020 --depth 2 ^expenses: --transpose -o report.csv".split() - subprocess.call(c) - c = r"sed -i s/\$//g report.csv".split() - subprocess.call(c) - report() - diff --git a/tools/report.sh b/tools/report.sh new file mode 100644 index 0000000..66d961f --- /dev/null +++ b/tools/report.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +CSV_FILE="data.csv" +REPORT_MD="report.md" +REPORT_PDF="/home/felixm/report.pdf" +YEAR="2018-04" +HLEDGER="hledger balance -M -V -b $YEAR --depth 1 --transpose -o $CSV_FILE" + +# Networth +$HLEDGER -H '^assets' +sed -i 's/\$//g' $CSV_FILE +python tofig.py $CSV_FILE "figure_1.png" + +$HLEDGER '^assets' +sed -i 's/\$//g' $CSV_FILE +sed -i 's/assets/cashflow/g' $CSV_FILE +python tofig.py $CSV_FILE "figure_2.png" --type bar + +$HLEDGER '^expenses' +sed -i 's/\$//g' $CSV_FILE +python tofig.py $CSV_FILE "figure_3.png" --type bar + +$HLEDGER '^income' +sed -i 's/\$-//g' $CSV_FILE +python tofig.py $CSV_FILE "figure_4.png" --type bar + +rm $CSV_FILE + +cat > $REPORT_MD <<- EOM +# Financial Report + +# Networth +![](figure_1.png) + +# Cashflow +![](figure_2.png) + +# Expenses +![](figure_3.png) + +# Income +![](figure_4.png) +EOM + +pandoc $REPORT_MD -o $REPORT_PDF +rm figure_* +rm $REPORT_MD + diff --git a/tools/tofig.py b/tools/tofig.py new file mode 100644 index 0000000..2b2b85b --- /dev/null +++ b/tools/tofig.py @@ -0,0 +1,40 @@ +import matplotlib.pyplot as plt +import pandas as pd +import argparse + + +def line_format(label): + """ + Convert time label to the format of pandas line plot + """ + month = label.month_name()[:3] + if month == 'Jan': + month = f'{label.year}\n{month}' + return month + + +def create_figure(args): + df = pd.read_csv(args.csv_file, index_col='Account', parse_dates=True) + df = df.drop(columns="Total:") + figsize=(10, 6) + if args.type == 'bar': + ax = df.plot(grid=True, kind='bar', figsize=figsize) + ax.set_xticklabels(map(lambda x: line_format(x), df.index)) + else: + ax = df.plot(grid=True, figsize=figsize) + plt.savefig(args.png_file) + # plt.show() + + +def get_args(): + parser = argparse.ArgumentParser(description='Transform a CSV file into a bar chart.') + parser.add_argument('csv_file', type=str, help='CSV data file') + parser.add_argument('png_file', type=str, help='Chart png file') + parser.add_argument('--type', default='', type=str, help='Chart png file') + return parser.parse_args() + + +if __name__ == "__main__": + args = get_args() + create_figure(args) +