Add script to generate pdf reports.

This commit is contained in:
Felix Martin 2020-09-03 18:10:11 -04:00
parent 26941a5041
commit 4f9b717d31
4 changed files with 97 additions and 34 deletions

View File

@ -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

View File

@ -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()

48
tools/report.sh Normal file
View File

@ -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

40
tools/tofig.py Normal file
View File

@ -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)