Adds the option for a user to see their 10 most recent transactions. #1

Open
jonny wants to merge 1 commit from jonny/matemat:transaction-list into main
5 changed files with 118 additions and 0 deletions

View file

@ -724,6 +724,40 @@ class MatematDatabase(object):
receipt = Receipt(receipt_id, transactions, user, created, datetime.utcnow()) receipt = Receipt(receipt_id, transactions, user, created, datetime.utcnow())
return receipt return receipt
def get_transactions(self, user: User) -> List[Transaction]:
transactions: List[Transaction] = []
with self.db.transaction() as cursor:
cursor.execute('''
SELECT
t.ta_id, t.value, t.old_balance, COALESCE(t.date, 0),
c.ta_id, d.ta_id, m.ta_id, c.product, m.agent, m.reason
FROM transactions AS t
LEFT JOIN consumptions AS c
ON t.ta_id = c.ta_id
LEFT JOIN deposits AS d
ON t.ta_id = d.ta_id
LEFT JOIN modifications AS m
ON t.ta_id = m.ta_id
WHERE t.user_id = :user_id
ORDER BY t.date DESC
LIMIT 10
''', {
'user_id': user.id
})
rows = cursor.fetchall()
for row in rows:
ta_id, value, old_balance, date, c, d, m, c_prod, m_agent, m_reason = row
if c == ta_id:
t: Transaction = Consumption(ta_id, user, value, old_balance, datetime.fromtimestamp(date), c_prod)
elif d == ta_id:
t = Deposit(ta_id, user, value, old_balance, datetime.fromtimestamp(date))
elif m == ta_id:
t = Modification(ta_id, user, value, old_balance, datetime.fromtimestamp(date), m_agent, m_reason)
else:
t = Transaction(ta_id, user, value, old_balance, datetime.fromtimestamp(date))
transactions.append(t)
return transactions
def generate_sales_statistics(self, from_date: datetime, to_date: datetime) -> Dict[str, Any]: def generate_sales_statistics(self, from_date: datetime, to_date: datetime) -> Dict[str, Any]:
consumptions: Dict[str, Tuple[int, int]] = dict() consumptions: Dict[str, Tuple[int, int]] = dict()
total_income: int = 0 total_income: int = 0

View file

@ -18,3 +18,4 @@ from .moduser import moduser
from .modproduct import modproduct from .modproduct import modproduct
from .userbootstrap import userbootstrap from .userbootstrap import userbootstrap
from .statistics import statistics from .statistics import statistics
from .transactions import transactions_page

View file

@ -0,0 +1,39 @@
from datetime import datetime
from bottle import route, redirect, request
from matemat.db import MatematDatabase
from matemat.webserver import template, session
from matemat.webserver.config import get_app_config, get_stock_provider
@route('/transactions')
def transactions_page():
"""
The transaction history page, showing a list of recent transactions.
"""
config = get_app_config()
session_id: str = session.start()
now = str(int(datetime.utcnow().timestamp()))
with MatematDatabase(config['DatabaseFile']) as db:
# Check whether a user is logged in
if session.has(session_id, 'authenticated_user'):
# Fetch the user id and authentication level (touchkey vs password) from the session storage
uid: int = session.get(session_id, 'authenticated_user')
authlevel: int = session.get(session_id, 'authentication_level')
# Fetch the user object from the database (for name display, price calculation and admin check)
user = db.get_user(uid)
transactions = db.get_transactions(user)
# Prepare a response with a jinja2 template
return template.render('transactions.html',
authuser=user, authlevel=authlevel,
setupname=config['InstanceName'], transactions=transactions)
else:
# If there are no admin users registered, jump to the admin creation procedure
if not db.has_admin_users():
redirect('/userbootstrap')
# If no user is logged in, fetch the list of users and render the userlist template
users = db.list_users(with_touchkey=True)
return template.render('userlist.html',
users=users, setupname=config['InstanceName'], now=now,
signup=(config.get('SignupEnabled', '0') == '1'))

View file

@ -33,6 +33,11 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if authlevel|default(0) > 0 %}
{% if authuser is defined %}
<a href="/transactions">Transactions</a>
{% endif %}
{% endif %}
</nav> </nav>
{% endblock %} {% endblock %}
</header> </header>

View file

@ -0,0 +1,39 @@
{% extends "base.html" %}
{% block header %}
{# Show the setup name, as set in the config file, as page title. Don't escape HTML entities. #}
<h1>{{ setupname|safe }}</h1>
{{ super() }}
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
</style>
{% endblock %}
{% block main %}
<div class="transactions-table">
List of 10 most recent transactions.
<table>
<tr>
<th>Date</th>
<th>Description</th>
<th>Value</th>
<th>Message</th>
</tr>
{% for t in transactions %}
<tr>
<td>{{ t.receipt_date }}</td>
<td>{{ t.receipt_description }}</td>
<td>{{ t.receipt_value }}</td>
<td>{{ t.receipt_message }}</td>
</tr>
{% endfor %}
</table>
</div>
{{ super() }}
{% endblock %}