Fixed bugs and added webinterface

This commit is contained in:
fleaz 2020-03-05 23:52:33 +01:00
parent 9c59b349c2
commit afbe8a96b1
11 changed files with 171 additions and 4 deletions

View file

@ -8,6 +8,7 @@ verify_ssl = true
[packages]
sqlalchemy = "*"
prompt-toolkit = "*"
bottle = "*"
[requires]
python_version = "3.8"

10
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "3abcef8be3462b1da61e99b34940773733b8cf76fc3ef77890b2d05098144f49"
"sha256": "e8dc56266a4018b0bdb774d18144085e717b5a9792bedfc7cb1325c78a641c19"
},
"pipfile-spec": 6,
"requires": {
@ -16,6 +16,14 @@
]
},
"default": {
"bottle": {
"hashes": [
"sha256:0819b74b145a7def225c0e83b16a4d5711fde751cd92bae467a69efce720f69e",
"sha256:43157254e88f32c6be16f8d9eb1f1d1472396a4e174ebd2bf62544854ecf37e7"
],
"index": "pypi",
"version": "==0.12.18"
},
"prompt-toolkit": {
"hashes": [
"sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e",

View file

@ -36,7 +36,7 @@ with open("transactions.csv") as fh:
print("Found transaction older than then oldest transction in the DB. Aborting")
sys.exit(1)
t = Transaction(date=date, name=name, iban=iban, amount=convert_amount(amount) * 100)
t = Transaction(date=date, name=name, iban=iban, amount=convert_amount(amount), description=description)
session.add(t)
session.commit()
count += 1

View file

@ -16,12 +16,27 @@ class Transaction(Base):
description = Column(String)
category_id = Column(Integer, ForeignKey("Category.id"))
def is_positive(self):
return self.amount > 0
def pretty_amount(self):
return "{0:.2f}".format(self.amount/100)
def get_date(self, format):
if format == "iso":
return self.date.strftime("%Y-%m-%d")
elif format == "de":
return self.date.strftime("%d.%m.%Y")
else:
return "UNKNOWN FORMAT"
class Category(Base):
__tablename__ = "Category"
id = Column(Integer, primary_key=True)
name = Column(String)
transactions = relationship("Category")
transactions = relationship("Transaction", backref="category")
parent_id = Column(Integer, ForeignKey("Category.id"))
children = relationship("Category", backref=backref("parent", remote_side=[id]))

40
serve.py Normal file
View file

@ -0,0 +1,40 @@
#! /usr/bin/env python3
from bottle import route, run, template
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from models import *
engine = create_engine("sqlite:///app.db")
Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()
@route('/')
def index():
return template('index')
@route('/categories')
def categories():
categories = session.query(Category).all()
categories = [c for c in categories if c.is_child()]
return template('categories', categories=categories)
@route('/category/<name>')
def category(name):
c = session.query(Category).filter(Category.name==name).first()
if c:
transactions = session.query(Transaction).filter(Transaction.category_id==c.id).all()
else:
transactions = []
return template('category', category=c,transactions=transactions)
@route('/transactions')
def transactions():
transactions = session.query(Transaction).all()
return template('transactions', transactions=transactions)
run(host='localhost', port=8080, reloader=True)

View file

@ -3,6 +3,7 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from models import *
from categories import add_category
import sys
from prompt_toolkit.completion import FuzzyWordCompleter
@ -15,7 +16,7 @@ Session = sessionmaker(bind=engine)
session = Session()
categories = session.query(Category).all()
category_lookup = [{c.full_name: c.id} for c in categories]
category_lookup = {c.full_name(): c.id for c in categories}
category_names = FuzzyWordCompleter([c.full_name() for c in categories])
unsorted = session.query(Transaction).filter(Transaction.category_id == None).all()
@ -36,5 +37,8 @@ for t in unsorted:
t.category_id = cat_id
session.add(t)
session.commit()
else:
print(f"Creating new category '{select}'")
add_category(select)
print("-" * 20)

34
views/base.tpl Normal file
View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="d">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Schmeckels</title>
<link href="https://unpkg.com/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
<link href="https://unpkg.com/@tailwindcss/custom-forms/dist/custom-forms.min.css" rel="stylesheet">
</head>
<body class="bg-grey-100 font-sans leading-normal tracking-normal">
<div class="bg-gray-300">
<ul class="flex pb-3 pt-3">
<li class="ml-12 mr-12">
<a class="text-blue-500 hover:text-blue-800" href="/">SCHMECKELS</a>
</li>
<li class="mr-2">
<a class="text-blue-500 hover:text-blue-800" href="/transactions">Transactions</a>
</li>
<li class="mr-2">
<a class="text-blue-500 hover:text-blue-800" href="/categories">Categories</a>
</li>
</ul>
</div>
<div class="container mx-auto">
{{!base}}
</div>
</body>
</html>

8
views/categories.tpl Normal file
View file

@ -0,0 +1,8 @@
% rebase("base.tpl")
List of categories:
<ul>
% for c in categories:
<li><a href="/category/{{ c.name }}">{{ c.full_name() }}</a></li>
% end
</ul>

26
views/category.tpl Normal file
View file

@ -0,0 +1,26 @@
% rebase("base.tpl")
<h1>Transaktionen aus {{ category.full_name() }}</h1>
<table class="table-auto">
<thead>
<tr>
<th class="px-4 py-2">Date</th>
<th class="px-4 py-2">Sender/Empfänger</th>
<th class="px-4 py-2">Verwendungszweck</th>
<th class="px-4 py-2">Betrag</th>
<th class="px-4 py-2">Kategorie</th>
</tr>
</thead>
<tbody>
% for t in transactions:
<tr>
<td class="border px-4 py-2">{{ t.get_date("de") }}</td>
<td class="border px-4 py-2">{{ t.name }}</td>
<td class="border px-4 py-2">{{ t.description }}</td>
<td class="border px-4 py-2 {{ 'text-green-500' if t.is_positive() else 'text-red-500' }}">{{ t.pretty_amount() }}</td>
<td class="border px-4 py-2">{{ t.category.full_name() if t.category else "-" }}</td>
</tr>
% end
</tbody>
</table>

3
views/index.tpl Normal file
View file

@ -0,0 +1,3 @@
% rebase("base.tpl")
<h1 class="text-2xl font-bold text-indigo-500">Hello World</h1>

28
views/transactions.tpl Normal file
View file

@ -0,0 +1,28 @@
% rebase("base.tpl")
<table class="table-auto">
<thead>
<tr>
<th class="px-4 py-2">Date</th>
<th class="px-4 py-2">Sender/Empfänger</th>
<th class="px-4 py-2">Verwendungszweck</th>
<th class="px-4 py-2">Betrag</th>
<th class="px-4 py-2">Kategorie</th>
</tr>
</thead>
<tbody>
% for t in transactions:
<tr>
<td class="border px-4 py-2">{{ t.get_date("de") }}</td>
<td class="border px-4 py-2">{{ t.name }}</td>
<td class="border px-4 py-2">{{ t.description }}</td>
<td class="border px-4 py-2 {{ 'text-green-500' if t.is_positive() else 'text-red-500' }}">{{ t.pretty_amount() }}</td>
% if t.category:
<td class="border px-4 py-2"> <a href="/category/{{ t.category.name }}"> {{ t.category.full_name()}}</a></td>
% else:
<td class="border px-4 py-2"> - </td>
% end
</tr>
% end
</tbody>
</table>