Compare commits
No commits in common. "c745d23ab87fc53b6e3a94041ad23a68dd62225b" and "1dab0d748f7b43f43b3fe1679ad9f6c3fcdce855" have entirely different histories.
c745d23ab8
...
1dab0d748f
@ -1,9 +1,34 @@
|
|||||||
|
import pandas as pd
|
||||||
from banking_breakdown import document_builder
|
from banking_breakdown import document_builder
|
||||||
from banking_breakdown import statement_parser
|
import subprocess
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from banking_breakdown import types
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
report_data = statement_parser.parse_statement("res/banking_statement_2023.csv")
|
categories = ["A", "B", "C", "D", "E", "F", "G"]
|
||||||
|
values = np.array([10, 12, 53, 12, 90, 23, 32])
|
||||||
|
values = values / values.sum() * 100
|
||||||
|
|
||||||
|
total_value = np.random.normal(size=10) + 4
|
||||||
|
net_income = np.diff(total_value)
|
||||||
|
|
||||||
|
category_overview_df = pd.DataFrame(
|
||||||
|
{"category": categories, "value": values.astype('int32')})
|
||||||
|
t = np.linspace(0, total_value.size, total_value.size)
|
||||||
|
total_value_df = pd.DataFrame({"t": t, "value": total_value})
|
||||||
|
t = np.linspace(0, net_income.size, net_income.size)
|
||||||
|
net_income_df = pd.DataFrame({"t": t, "value": net_income})
|
||||||
|
|
||||||
|
report_data = types.ReportData(category_overview=category_overview_df,
|
||||||
|
net_income=net_income_df,
|
||||||
|
total_value=total_value_df)
|
||||||
|
|
||||||
document_builder.build_document(report_data)
|
document_builder.build_document(report_data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,6 @@ def _serialize_report_data(report_data: types.ReportData):
|
|||||||
report_data.category_overview.to_csv('build/category_overview.csv',
|
report_data.category_overview.to_csv('build/category_overview.csv',
|
||||||
index=False)
|
index=False)
|
||||||
report_data.total_value.to_csv('build/total_value.csv', index=False)
|
report_data.total_value.to_csv('build/total_value.csv', index=False)
|
||||||
report_data.detailed_balance.to_csv('build/detailed_balance.csv',
|
|
||||||
index=False)
|
|
||||||
|
|
||||||
|
|
||||||
def _compile_document():
|
def _compile_document():
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
import typing
|
|
||||||
import pandas as pd
|
|
||||||
from banking_breakdown import types
|
|
||||||
import json
|
|
||||||
import re
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
|
|
||||||
def _read_regex_dict(regex_file: str = "res/category_regexes.json"):
|
|
||||||
with open(regex_file, 'r') as f:
|
|
||||||
return json.load(f)
|
|
||||||
|
|
||||||
|
|
||||||
def _tag_with_category(df: pd.DataFrame) -> pd.DataFrame:
|
|
||||||
regex_dict = _read_regex_dict()
|
|
||||||
|
|
||||||
return df
|
|
||||||
|
|
||||||
|
|
||||||
def _compute_total_balance(df: pd.DataFrame) -> pd.DataFrame:
|
|
||||||
stripped_df = pd.DataFrame(
|
|
||||||
{'t': df["Buchungstag"], 'value': df["Saldo nach Buchung"]})
|
|
||||||
|
|
||||||
stripped_df.index = stripped_df['t']
|
|
||||||
gb = stripped_df.groupby(pd.Grouper(freq='M'))
|
|
||||||
|
|
||||||
result = gb.tail(1)['value'].reset_index()
|
|
||||||
#result['t'] = result['t'].apply(lambda dt: dt.replace(day=1))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _compute_net_income(df: pd.DataFrame) -> pd.DataFrame:
|
|
||||||
stripped_df = pd.DataFrame({'t': df["Buchungstag"], 'value': df["Betrag"]})
|
|
||||||
|
|
||||||
result = stripped_df.resample(rule='M', on="t").sum().reset_index()
|
|
||||||
#result['t'] = result['t'].apply(lambda dt: dt.replace(day=1))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _compute_category_overview(df: pd.DataFrame) -> pd.DataFrame:
|
|
||||||
categories = ["A", "B", "C", "D", "E", "F", "G"]
|
|
||||||
values = np.array([10, 12, 53, 12, 90, 23, 32])
|
|
||||||
values = values / values.sum() * 100
|
|
||||||
values = np.round(values, decimals=1)
|
|
||||||
values[-1] += 100 - np.sum(values)
|
|
||||||
|
|
||||||
category_overview_df = pd.DataFrame(
|
|
||||||
{"category": categories, "value": values})
|
|
||||||
|
|
||||||
return category_overview_df
|
|
||||||
|
|
||||||
|
|
||||||
def _compute_detailed_balance(df: pd.DataFrame) -> pd.DataFrame:
|
|
||||||
return pd.DataFrame({'t': df["Buchungstag"],
|
|
||||||
'value': df["Saldo nach Buchung"]})
|
|
||||||
|
|
||||||
|
|
||||||
def parse_statement(filename: str) -> types.ReportData:
|
|
||||||
df = pd.read_csv(filename, delimiter=';', decimal=",")
|
|
||||||
df["Buchungstag"] = pd.to_datetime(df["Buchungstag"], format='%d.%m.%Y')
|
|
||||||
|
|
||||||
category_overview_df = _compute_category_overview(df)
|
|
||||||
total_balance_df = _compute_total_balance(df)
|
|
||||||
net_income_df = _compute_net_income(df)
|
|
||||||
detailed_balance_df = _compute_detailed_balance(df)
|
|
||||||
|
|
||||||
return types.ReportData(category_overview_df,
|
|
||||||
net_income_df,
|
|
||||||
total_balance_df,
|
|
||||||
detailed_balance_df)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
report_data = parse_statement("../res/banking_statement_2023.csv")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -7,4 +7,3 @@ class ReportData:
|
|||||||
category_overview: pd.DataFrame
|
category_overview: pd.DataFrame
|
||||||
net_income: pd.DataFrame
|
net_income: pd.DataFrame
|
||||||
total_value: pd.DataFrame
|
total_value: pd.DataFrame
|
||||||
detailed_balance: pd.DataFrame
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
\usepackage{amsmath}
|
\usepackage{amsmath}
|
||||||
\usepackage{pgfplots}
|
\usepackage{pgfplots}
|
||||||
\pgfplotsset{compat=newest}
|
\pgfplotsset{compat=newest}
|
||||||
\usetikzlibrary{pgfplots.dateplot}
|
|
||||||
|
|
||||||
% Other packages
|
% Other packages
|
||||||
\usepackage[a4paper, total={12cm, 25cm}]{geometry}
|
\usepackage[a4paper, total={12cm, 25cm}]{geometry}
|
||||||
@ -31,10 +30,6 @@
|
|||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
|
||||||
\makeatletter
|
|
||||||
\newcommand*\shortyear[1]{\expandafter\@gobbletwo\number\numexpr#1\relax}
|
|
||||||
\makeatother
|
|
||||||
|
|
||||||
\newcommand{\slice}[6]{
|
\newcommand{\slice}[6]{
|
||||||
\pgfmathparse{0.5*#1+0.5*#2}
|
\pgfmathparse{0.5*#1+0.5*#2}
|
||||||
\let\midangle\pgfmathresult
|
\let\midangle\pgfmathresult
|
||||||
@ -141,34 +136,15 @@
|
|||||||
|
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
\begin{axis}[
|
\begin{axis}[
|
||||||
date coordinates in=x,
|
|
||||||
width=\textwidth,
|
width=\textwidth,
|
||||||
height=0.375\textwidth,
|
height=0.375\textwidth,
|
||||||
ylabel={Net income in €},
|
ylabel={Net income in €},
|
||||||
y label style={at={(-0.1,0.5)},anchor=south},
|
y label style={at={(-0.1,0.5)},anchor=south},
|
||||||
xticklabel=\month.\shortyear{\year},
|
|
||||||
xtick=data,
|
|
||||||
xticklabel style={
|
|
||||||
rotate=60,
|
|
||||||
anchor=near xticklabel,
|
|
||||||
},
|
|
||||||
grid,
|
|
||||||
enlarge x limits=0.03,
|
|
||||||
]
|
]
|
||||||
% Dummy plot to set x axis ticks
|
\addplot+[ybar, color=scol2, fill=scol2, line width=1pt]
|
||||||
\addplot[draw=none]
|
|
||||||
table[col sep=comma, x=t, y=value]
|
|
||||||
{net_income.csv};
|
|
||||||
|
|
||||||
% Dummy plot to set x axis scale
|
|
||||||
\addplot[draw=none]
|
|
||||||
table[col sep=comma, x=t, y=value]
|
|
||||||
{detailed_balance.csv};
|
|
||||||
|
|
||||||
\addplot[ybar, color=scol2, fill=scol2, line width=1pt]
|
|
||||||
table[col sep=comma, x=t, y=value, discard if lt={value}{0}]
|
table[col sep=comma, x=t, y=value, discard if lt={value}{0}]
|
||||||
{net_income.csv};
|
{net_income.csv};
|
||||||
\addplot[ybar, color=scol0, fill=scol0, line width=1pt]
|
\addplot+[ybar, color=scol0, fill=scol0, line width=1pt]
|
||||||
table[col sep=comma, x=t, y=value, discard if gt={value}{0}]
|
table[col sep=comma, x=t, y=value, discard if gt={value}{0}]
|
||||||
{net_income.csv};
|
{net_income.csv};
|
||||||
\end{axis}
|
\end{axis}
|
||||||
@ -179,31 +155,15 @@
|
|||||||
|
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
\begin{axis}[
|
\begin{axis}[
|
||||||
date coordinates in=x,
|
|
||||||
width=\textwidth,
|
width=\textwidth,
|
||||||
height=0.375\textwidth,
|
height=0.375\textwidth,
|
||||||
|
area style,
|
||||||
ylabel={Total balance in €},
|
ylabel={Total balance in €},
|
||||||
y label style={at={(-0.1,0.5)},anchor=south},
|
y label style={at={(-0.1,0.5)},anchor=south},
|
||||||
xticklabel=\month.\shortyear{\year},
|
|
||||||
xtick=data,
|
|
||||||
enlarge x limits=0.03,
|
|
||||||
xticklabel style={
|
|
||||||
rotate=60,
|
|
||||||
anchor=near xticklabel,
|
|
||||||
},
|
|
||||||
grid,
|
|
||||||
]
|
]
|
||||||
% Dummy plot to set x axis ticks
|
\addplot+[mark=none, color=scol1, line width=1pt]
|
||||||
\addplot[draw=none]
|
|
||||||
table[col sep=comma, x=t, y=value]
|
table[col sep=comma, x=t, y=value]
|
||||||
{total_value.csv};
|
{total_value.csv} \closedcycle;
|
||||||
|
|
||||||
\addplot[scol3, mark=none, line width=1pt]
|
|
||||||
table[col sep=comma, x=t, y=value]
|
|
||||||
{detailed_balance.csv};
|
|
||||||
\addplot[scol1, mark=none, line width=1pt]
|
|
||||||
table[col sep=comma, x=t, y=value]
|
|
||||||
{total_value.csv};
|
|
||||||
\end{axis}
|
\end{axis}
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
@ -211,6 +171,5 @@
|
|||||||
\caption{Development of account balance over time}
|
\caption{Development of account balance over time}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user