Просмотр исходного кода

Work around issue with timestamp as local time in db and update Mock code

Daniel Sheffield 3 лет назад
Родитель
Сommit
e009e8aac6
2 измененных файлов с 38 добавлено и 18 удалено
  1. 23 11
      grocery_transactions.py
  2. 15 7
      txn_view.py

+ 23 - 11
grocery_transactions.py

@@ -7,6 +7,8 @@
 # THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
 import pandas as pd
 from txn_view import get_statement as get_session_transactions_statement
+from dateutil.parser import parse as parse_time
+from datetime import datetime
 try:
     import psycopg2
     from psycopg2.sql import SQL
@@ -14,6 +16,9 @@ try:
     MOCK = False
 except:
     from faker import Faker
+    def cursor_as_dict(cur):
+        yield from cur.fetchall()
+        
     Faker.seed(4321)
     fake = Faker()
     MOCK = True
@@ -114,7 +119,6 @@ import urwid
 from urwid import numedit
 from decimal import Decimal
 import time
-import datetime
 import itertools
 from collections import (
     OrderedDict,
@@ -135,7 +139,7 @@ class mock_cur(object):
         pass
     
     def fetchall(self):
-        yield from self.records
+        yield from (i for i in self.records)
     
     def close(self):
         pass
@@ -150,12 +154,16 @@ except:
 
 if MOCK:
     records = [{
-        'ts': datetime.datetime(2021, 8, 29, 14, 8, 0, 0),
+        'ts': datetime(2021, 8, 29, 14, 8, 0, 0),
+        'id': 2,
+        'code': fake.store()[:4],
         'store': 'Countdown',
         'price': 4.30,
+        '$/unit': 4.3/250.0,
         'quantity': 250.0,
         'unit': 'g',
         'organic': False,
+        'total': 0,
         'description': 'Whittakers',
         'product': 'Dark Chocolate',
         'group': 'Treats',
@@ -176,12 +184,16 @@ if MOCK:
             words.append('organic')
         
         records.append({
-            'ts': datetime.datetime(2021, 8, 29, 14, 8, 0, 0),
+            'ts': datetime(2021, 8, 29, 14, 8, 0, 0),
+            'id': 3,
+            'code': fake.store()[:4],
             'store': fake.store(),
             'price': price,
+            '$/unit': price/quantity,
             'quantity': quantity,
             'unit': unit,
             'organic': organic,
+            'total': 0,
             'description': ' '.join([
                 product[0],
                 *fake.description(ext_word_list=words).split()
@@ -190,10 +202,7 @@ if MOCK:
             'group': product[2],
             'category': product[1],
         })
-    col_idx_map = dict([ ( k, idx ) for idx,k in enumerate(sorted(records[0].keys())) ])
-    records = [
-        [ r[k] for k in sorted(r.keys()) ] for r in records
-    ]
+    
     conn = mock_conn()
     cur = mock_cur(records)
 else:
@@ -254,16 +263,19 @@ display = lambda data, name: display_map[name](data) if name in display_map else
 cur.execute("BEGIN")
 
 def get_session_transactions(date, store):
-    #print(cur.mogrify(get_session_transactions_statement(date,store,full_name=True)).decode("utf-8"))
+    statement = get_session_transactions_statement(parse_time(date), store, full_name=True, exact_time=True)
+    #print(cur.mogrify(statement).decode("utf-8"))
     #input()
-    cur.execute(get_session_transactions_statement(date,store,full_name=True))
+    cur.execute(statement)
     df = pd.DataFrame(cursor_as_dict(cur))
+    if df.empty:
+        return ''
     return df.drop(labels=[
         'id', 'ts', 'store', 'code',
     ], axis=1).to_string(header=[
         'Description', 'Volume', 'Unit', 'Price', '$/unit', 'Total',
         'Group', 'Category', 'Product', 'Organic',
-    ], justify='justify-all', max_colwidth=36, index=False)
+    ], justify='justify-all', max_colwidth=38, index=False)
 
 def get_transactions_statement():
     return SQL("SELECT * FROM transaction_view")

+ 15 - 7
txn_view.py

@@ -26,7 +26,7 @@ select = OrderedDict([
     ('organic', Identifier('organic')),
 ])
 
-def get_where(date, store, full_name=False, exact_date=False):
+def get_where(date, store, full_name=False, exact_time=False):
     where = [ ]
     if store is not None:
         where.append(SQL(' ').join([
@@ -34,14 +34,20 @@ def get_where(date, store, full_name=False, exact_date=False):
             SQL('='),
             Literal(store)
         ]))
+    tz_hack_local = SQL("::timestamp with time zone")
+    tz_hack = SQL("||'+00'::text")
     where.append(
-        SQL("{ts} BETWEEN {date}::date AND {date}::date + {interval}::interval").format(
+        SQL("({ts}{tz_hack}){tz_hack_local} BETWEEN {date}{tz_hack_local}::date AND {date}{tz_hack_local}::date + {interval}::interval").format(
             ts=Identifier('ts'),
             date=Literal(str(date)),
             interval=Literal('23 hours 59 minutes 59 seconds'),
-        ) if not exact_date else SQL("{ts} = {date}").format(
+            tz_hack=tz_hack,
+            tz_hack_local=tz_hack_local,
+        ) if not exact_time else SQL("({ts}{tz_hack}){tz_hack_local} = {date}{tz_hack_local}").format(
             ts=Identifier('ts'),
             date=Literal(str(date)),
+            tz_hack=tz_hack,
+            tz_hack_local=tz_hack_local,
         )
     )
     return SQL('').join([
@@ -50,9 +56,9 @@ def get_where(date, store, full_name=False, exact_date=False):
         SQL("\n  AND ").join(where),
     ])
 
-def get_statement(date, store, full_name=False):
+def get_statement(date, store, full_name=False, exact_time=False):
     statement = SQL('\n').join([
-        SQL('\n').join([
+        SQL('').join([
             SQL("SELECT"
                 "\n  "),
             SQL(','
@@ -62,7 +68,7 @@ def get_statement(date, store, full_name=False):
         ]),
         SQL('').join([
             SQL("FROM"
-                "\n      "),
+                "\n       "),
             SQL("\n  JOIN ").join([
                 SQL("transactions"),
                 SQL("{table} ON {table}.{key} = {index}").format(
@@ -92,7 +98,9 @@ def get_statement(date, store, full_name=False):
                 ),
             ]),
         ]),
-        get_where(date,store, full_name=full_name),
+        get_where(date if exact_time else date.replace(
+            hour=0, minute=0, second=0, microsecond=0
+        ), store, full_name=full_name, exact_time=exact_time),
         SQL('ORDER BY {_id} DESC').format(_id=Identifier('transactions','id')),
     ])
     return statement