Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fix kassenbuch get_buchungen for microseconds #143

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions FabLabKasse/kassenbuch.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ class NoDataFound(Exception):
class Rechnung(object):

def __init__(self, id=None, datum=None):
assert(isinstance(id, (int, type(None))))
assert(isinstance(datum, (datetime, type(None))))
self.id = id

if not datum:
self.datum = datetime.now()
else:
Expand Down Expand Up @@ -248,6 +249,8 @@ def print_receipt(self, cfg, zahlungsart="BAR"):
class Buchung(object):

def __init__(self, konto, betrag, rechnung=None, kommentar=None, id=None, datum=None):
assert(isinstance(id, (int, type(None))))
assert(isinstance(datum, (datetime, type(None))))
self.id = id
if not datum:
self.datum = datetime.now()
Expand Down Expand Up @@ -362,6 +365,8 @@ def _date_query_generator(from_table=None, from_date=None, until_date=None):
:type until_date: datetime.datetime | None
:return: query string
"""
assert isinstance(from_date, (datetime, type(None)))
assert isinstance(until_date, (datetime, type(None)))
# TODO comparing against these strings might make problems with py3
# --> best import unicode_literals from future
# --> check whole file if this import is problematic
Expand All @@ -371,15 +376,15 @@ def _date_query_generator(from_table=None, from_date=None, until_date=None):

query = "SELECT id FROM {0}".format(from_table)
if from_date and until_date:
query = query + " WHERE datum >= Datetime('{from_date}') AND datum < Datetime('{until_date}')".format(
query = query + " WHERE Datetime(datum) >= Datetime('{from_date}') AND Datetime(datum) < Datetime('{until_date}')".format(
from_date=from_date, until_date=until_date
)
elif from_date:
query = query + " WHERE datum >= Datetime('{from_date}')".format(
query = query + " WHERE Datetime(datum) >= Datetime('{from_date}')".format(
from_date=from_date
)
elif until_date:
query = query + " WHERE datum < Datetime('{until_date}')".format(
query = query + " WHERE Datetime(datum) < Datetime('{until_date}')".format(
until_date=until_date
)

Expand All @@ -393,6 +398,8 @@ def get_buchungen(self, from_date=None, until_date=None):
"""
get accounting records between the given dates. If a date is ``None``, no filter will be applied.

The time comparison will ignore the fractional second part.

:param from_date: start datetime (included)
:param until_date: end datetime (not included)
:type from_date: datetime.datetime | None
Expand All @@ -415,6 +422,8 @@ def get_rechnungen(self, from_date=None, until_date=None):
"""
get invoices between the given dates. If a date is ``None``, no filter will be applied.

The time comparison will ignore the fractional second part.

:param from_date: start datetime (included)
:param until_date: end datetime (not included)
:type from_date: datetime.datetime | None
Expand Down
29 changes: 21 additions & 8 deletions FabLabKasse/test_kassenbuch.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import unittest
from FabLabKasse.kassenbuch import Kasse, Kunde, Buchung, Rechnung, NoDataFound, parse_args
from FabLabKasse.kassenbuch import argparse_parse_date, argparse_parse_currency
from hypothesis import given
from hypothesis import given, example
from hypothesis.strategies import text
import hypothesis.extra.datetime as hypothesis_datetime
import dateutil
Expand Down Expand Up @@ -101,14 +101,14 @@ def test_accounting_database_client_creation(self, clientname):
def test_datestring_generator(self, from_date, until_date):
"""test the datestring_generator in Kasse"""
query = Kasse._date_query_generator('buchung', from_date=from_date, until_date=until_date)
pristine_query = "SELECT id FROM buchung WHERE datum >= Datetime('{from_date}') AND " \
"datum < Datetime('{until_date}')".format(from_date=from_date, until_date=until_date)
pristine_query = "SELECT id FROM buchung WHERE Datetime(datum) >= Datetime('{from_date}') AND " \
"Datetime(datum) < Datetime('{until_date}')".format(from_date=from_date, until_date=until_date)
self.assertEqual(query, pristine_query)
query = Kasse._date_query_generator('buchung', until_date=until_date)
pristine_query = "SELECT id FROM buchung WHERE datum < Datetime('{until_date}')".format(until_date=until_date)
pristine_query = "SELECT id FROM buchung WHERE Datetime(datum) < Datetime('{until_date}')".format(until_date=until_date)
self.assertEqual(query, pristine_query)
query = Kasse._date_query_generator('buchung', from_date=from_date)
pristine_query = "SELECT id FROM buchung WHERE datum >= Datetime('{from_date}')".format(from_date=from_date)
pristine_query = "SELECT id FROM buchung WHERE Datetime(datum) >= Datetime('{from_date}')".format(from_date=from_date)
self.assertEqual(query, pristine_query)

@given(rechnung_date=hypothesis_datetime.datetimes(min_year=1900, timezones=[]),
Expand All @@ -117,11 +117,15 @@ def test_datestring_generator(self, from_date, until_date):
def test_get_rechnungen(self, rechnung_date, from_date, until_date):
"""test the get_rechnungen function"""
kasse = Kasse(sqlite_file=':memory:')
rechnung = Rechnung(datum=rechnung_date.strftime('%Y-%m-%d %H:%M:%S.%f'))
rechnung = Rechnung(datum=rechnung_date)
rechnung.store(kasse.cur)
kasse.con.commit()

query = kasse.get_rechnungen(from_date, until_date)
# the time comparison does not care about fractions of a second
from_date = from_date.replace(microsecond=0)
until_date = until_date.replace(microsecond=0)
rechnung_date = rechnung_date.replace(microsecond=0)
if from_date <= rechnung_date < until_date:
self.assertTrue(query)
else:
Expand All @@ -130,22 +134,31 @@ def test_get_rechnungen(self, rechnung_date, from_date, until_date):
@given(buchung_date=hypothesis_datetime.datetimes(min_year=1900, timezones=[]),
from_date=hypothesis_datetime.datetimes(min_year=1900, timezones=[]),
until_date=hypothesis_datetime.datetimes(min_year=1900, timezones=[]))
# corner case: microseconds
@example(buchung_date=datetime(2000, 1, 1, 0, 0), from_date=datetime(2000, 1, 1, 0, 0), until_date=datetime(2000, 1, 1, 0, 0, 0, 1))
def test_get_buchungen(self, buchung_date, from_date, until_date):
"""test the get_buchungen function"""
kasse = Kasse(sqlite_file=':memory:')
rechnung = Rechnung(datum=buchung_date.strftime('%Y-%m-%d %H:%M:%S.%f'))
rechnung = Rechnung(datum=buchung_date)
rechnung.store(kasse.cur)
buchung = Buchung(konto='somewhere',
betrag='0',
rechnung=rechnung.id,
kommentar="Passing By And Thought I'd Drop In",
datum=buchung_date.strftime('%Y-%m-%d %H:%M:%S.%f'))
datum=buchung_date)
buchung._store(kasse.cur)
kasse.con.commit()

#TODO load_from_row ist sehr anfällig gegen kaputte datetimes, das sollte am besten schon sauber in die Datenbank
query = kasse.get_buchungen(from_date, until_date)
# the time comparison does not care about fractions of a second
from_date = from_date.replace(microsecond=0)
until_date = until_date.replace(microsecond=0)
buchung_date = buchung_date.replace(microsecond=0)
if from_date <= buchung_date < until_date:
self.assertTrue(query)
else:
self.assertFalse(query)

if __name__ == "__main__":
unittest.main()