From afbe8a96b1c82c98b29cc3300420bbe83d49ba48 Mon Sep 17 00:00:00 2001 From: fleaz Date: Thu, 5 Mar 2020 23:52:33 +0100 Subject: [PATCH] Fixed bugs and added webinterface --- Pipfile | 1 + Pipfile.lock | 10 +++++++++- import.py | 2 +- models.py | 17 ++++++++++++++++- serve.py | 40 ++++++++++++++++++++++++++++++++++++++++ sort.py | 6 +++++- views/base.tpl | 34 ++++++++++++++++++++++++++++++++++ views/categories.tpl | 8 ++++++++ views/category.tpl | 26 ++++++++++++++++++++++++++ views/index.tpl | 3 +++ views/transactions.tpl | 28 ++++++++++++++++++++++++++++ 11 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 serve.py create mode 100644 views/base.tpl create mode 100644 views/categories.tpl create mode 100644 views/category.tpl create mode 100644 views/index.tpl create mode 100644 views/transactions.tpl diff --git a/Pipfile b/Pipfile index 02f3dd0..1499eb6 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ verify_ssl = true [packages] sqlalchemy = "*" prompt-toolkit = "*" +bottle = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index dcb2a65..fbd3b37 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -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", diff --git a/import.py b/import.py index 3a54497..aa27fab 100644 --- a/import.py +++ b/import.py @@ -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 diff --git a/models.py b/models.py index c93d45e..39e684e 100644 --- a/models.py +++ b/models.py @@ -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])) diff --git a/serve.py b/serve.py new file mode 100644 index 0000000..45ffb07 --- /dev/null +++ b/serve.py @@ -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/') +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) diff --git a/sort.py b/sort.py index 798abbc..f38bda8 100644 --- a/sort.py +++ b/sort.py @@ -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) diff --git a/views/base.tpl b/views/base.tpl new file mode 100644 index 0000000..693bf16 --- /dev/null +++ b/views/base.tpl @@ -0,0 +1,34 @@ + + + + + + + + Schmeckels + + + + + +
+ +
+
+ + {{!base}} +
+ + + + diff --git a/views/categories.tpl b/views/categories.tpl new file mode 100644 index 0000000..88e1671 --- /dev/null +++ b/views/categories.tpl @@ -0,0 +1,8 @@ +% rebase("base.tpl") + +List of categories: + diff --git a/views/category.tpl b/views/category.tpl new file mode 100644 index 0000000..971a209 --- /dev/null +++ b/views/category.tpl @@ -0,0 +1,26 @@ +% rebase("base.tpl") + +

Transaktionen aus {{ category.full_name() }}

+ + + + + + + + + + + + +% for t in transactions: + + + + + + + +% end + +
DateSender/EmpfängerVerwendungszweckBetragKategorie
{{ t.get_date("de") }}{{ t.name }}{{ t.description }}{{ t.pretty_amount() }}{{ t.category.full_name() if t.category else "-" }}
diff --git a/views/index.tpl b/views/index.tpl new file mode 100644 index 0000000..07bc924 --- /dev/null +++ b/views/index.tpl @@ -0,0 +1,3 @@ +% rebase("base.tpl") + +

Hello World

diff --git a/views/transactions.tpl b/views/transactions.tpl new file mode 100644 index 0000000..933b529 --- /dev/null +++ b/views/transactions.tpl @@ -0,0 +1,28 @@ +% rebase("base.tpl") + + + + + + + + + + + + +% for t in transactions: + + + + + + % if t.category: + + % else: + + % end + +% end + +
DateSender/EmpfängerVerwendungszweckBetragKategorie
{{ t.get_date("de") }}{{ t.name }}{{ t.description }}{{ t.pretty_amount() }} {{ t.category.full_name()}} -