Browse Source

Order in the db and use pandas to format display

Daniel Sheffield 3 years ago
parent
commit
1470a85ce8
2 changed files with 80 additions and 24 deletions
  1. 9 1
      grocery_transactions.py
  2. 71 23
      txn_view.py

+ 9 - 1
grocery_transactions.py

@@ -5,6 +5,7 @@
 # All rights reserved
 #
 # THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
+import pandas as pd
 from txn_view import get_statement as get_session_transactions_statement
 try:
     import psycopg2
@@ -254,8 +255,15 @@ cur.execute("BEGIN")
 
 def get_session_transactions(date, store):
     #print(cur.mogrify(get_session_transactions_statement(date,store,full_name=True)).decode("utf-8"))
+    #input()
     cur.execute(get_session_transactions_statement(date,store,full_name=True))
-    return '\n'.join(map(lambda x: '|'.join(map(str, x)), cur.fetchall()))
+    df = pd.DataFrame(cursor_as_dict(cur))
+    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)
 
 def get_transactions_statement():
     return SQL("SELECT * FROM transaction_view")

+ 71 - 23
txn_view.py

@@ -5,46 +5,94 @@ from psycopg2.sql import (
     Placeholder,
     Composed,
 )
+from collections import (
+    OrderedDict,
+)
 
-select = {
-    'ts': SQL("""date_part('day',ts)||'/'||date_part('month',ts)||' '||date_part('hour',ts)::int%12"""),
-    'shop': Identifier('code'),
-    'description': SQL("""substr(description,1,32)"""),
-    'volume': Identifier('quantity'),
-    'unit': SQL("""substr(unit,1,4)"""),
-    'price': Identifier('price'),
-    '$/unit': SQL("""TRUNC(price/quantity,4)"""),
-    'total': SQL("""sum(transaction_view.price) OVER (PARTITION BY transaction_view.ts::date ORDER BY transaction_view.ts, transaction_view.description ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)"""),
-    'group': SQL("""substr(product,1,10) AS product, substr(category,1,8) AS category, substr("group",1,9)"""),
-    'og': Identifier('organic'),
-}
+select = OrderedDict([
+    ('id', Identifier('transactions','id')),
+    ('ts', SQL("""date_part('day',ts)||'/'||date_part('month',ts)||' '||date_part('hour',ts)::int%12""")),
+    ('store', Identifier('stores', 'name')),
+    ('code', Identifier('stores', 'code')),
+    ('description', Identifier('transactions','description')),
+    ('volume', Identifier('quantity')),
+    ('unit', Identifier('units', 'name')),
+    ('price', Identifier('price')),
+    ('$/unit', SQL("""TRUNC(price/quantity,4)""")),
+    ('total', SQL("""sum(transactions.price) OVER (PARTITION BY transactions.ts::date ORDER BY transactions.id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)""")),
+    ('group', Identifier('groups','name')),
+    ('category', Identifier('categories','name')),
+    ('product', Identifier('products','name')),
+    ('organic', Identifier('organic')),
+])
 
-def get_where(date, store, full_name=False):
+def get_where(date, store, full_name=False, exact_date=False):
     where = [ ]
     if store is not None:
         where.append(SQL(' ').join([
-            Identifier('store' if full_name else 'code'), SQL('='), Literal(store)
+            Identifier('stores', 'name' if full_name else 'code'),
+            SQL('='),
+            Literal(store)
         ]))
     where.append(
         SQL("{ts} BETWEEN {date}::date AND {date}::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(
+            ts=Identifier('ts'),
+            date=Literal(str(date)),
         )
     )
-    return SQL("\n      ").join([
-        SQL("WHERE"),
+    return SQL('').join([
+        SQL("WHERE"
+            "\n      "),
         SQL("\n  AND ").join(where),
     ])
 
 def get_statement(date, store, full_name=False):
-    statement = SQL("\n").join([
-        SQL("\n  ").join([
-            SQL("SELECT"),
-            SQL(',\n  ').join([
+    statement = SQL('\n').join([
+        SQL('\n').join([
+            SQL("SELECT"
+                "\n  "),
+            SQL(','
+                "\n  ").join([
                 SQL(' ').join([v, SQL('AS'), Identifier(f'{k}')]) for k, v in select.items()
-            ])]),
-        SQL("FROM transaction_view"),
-        get_where(date,store, full_name=full_name)
+            ])
+        ]),
+        SQL('').join([
+            SQL("FROM"
+                "\n      "),
+            SQL("\n  JOIN ").join([
+                SQL("transactions"),
+                SQL("{table} ON {table}.{key} = {index}").format(
+                    table=Identifier('units'),
+                    key=Identifier('id'),
+                    index=Identifier('unit_id'),
+                ),
+                SQL("{table} ON {table}.{key} = {index}").format(
+                    table=Identifier('stores'),
+                    key=Identifier('id'),
+                    index=Identifier('store_id')
+                ),
+                SQL("{table} ON {table}.{key} = {index}").format(
+                    table=Identifier('products'),
+                    key=Identifier('id'),
+                    index=Identifier('product_id')
+                ),
+                SQL("{table} ON {table}.{key} = {index}").format(
+                    table=Identifier('categories'),
+                    key=Identifier('id'),
+                    index=Identifier('category_id')
+                ),
+                SQL("{table} ON {table}.{key} = {index}").format(
+                    table=Identifier('groups'),
+                    key=Identifier('id'),
+                    index=Identifier('group_id')
+                ),
+            ]),
+        ]),
+        get_where(date,store, full_name=full_name),
+        SQL('ORDER BY {_id} DESC').format(_id=Identifier('transactions','id')),
     ])
     return statement