diff --git a/.vscode/settings.json b/.vscode/settings.json index 8e3871d..56451a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "**/__pycache__": true, "**/.vscode": true, "**/*.map": true, + "**/*.css.map": true, "static/css/base.css": true, "static/css/home.css": true, "static/css/navbar.css": true, diff --git a/web/account.py b/web/account.py index 8ecc703..fa8de60 100755 --- a/web/account.py +++ b/web/account.py @@ -17,7 +17,6 @@ REDIRECT_URI = 'https://nova-oss.com/callback/discord' # REDIRECT_URI = 'http://localhost:2211/callback/discord' SCOPES = ['identify'] -@functools.lru_cache(maxsize=128) def get_user(discord_id: int) -> dict: res = requests.get( url=f'http://localhost:2333/users?discord_id={discord_id}', diff --git a/web/finances.py b/web/finances.py index b8998b5..c86c2b8 100755 --- a/web/finances.py +++ b/web/finances.py @@ -4,6 +4,7 @@ import time import json import flask import requests +import pandas as pd from dotenv import load_dotenv @@ -26,29 +27,70 @@ def register(app): try: data = get_finances() except Exception: - return flask.Response('Error fetching finances from database. This might be cause the data is still being processed. Sorry.', status=500) + return flask.Response('Error fetching finances from database. This might be cause the data is still being processed. Please allow up to a few minutes.', status=500) + + donations = data['donations'] + expenses = data['expenses'] finances = { 'last_update': data['timestamp'], - 'donations_total': round(sum([i['amount_usd'] for i in data['donations']])), - 'donations_num': len(data['donations']), - 'donations_avg': round(sum([i['amount_usd'] for i in data['donations']]) / len(data['donations']), 2), - 'donations_max': round(max([i['amount_usd'] for i in data['donations']])), - 'most_used_donation_currency': max(data['donations'], key=lambda x: x['amount_usd'])['currency'], + 'donations_total': round(sum([i['amount_usd'] for i in donations])), + 'donations_num': len(donations), + 'donations_avg': round(sum([i['amount_usd'] for i in donations]) / len(donations), 2), + 'donations_max': round(max([i['amount_usd'] for i in donations])), + 'most_used_donation_currency': max(donations, key=lambda x: x['amount_usd'])['currency'], - 'expenses_total': round(sum([i['amount_usd'] for i in data['expenses']])), - 'expenses_wages': round(sum([i['amount_usd'] for i in data['expenses'] if i['type'] == 'wage'])), - 'most_used_expense_currency': max(data['expenses'], key=lambda x: x['amount_usd'])['currency'], + 'expenses_total': round(sum([i['amount_usd'] for i in expenses])), + 'expenses_wages': round(sum([i['amount_usd'] for i in expenses if i['type'] == 'wage'])), + 'most_used_expense_currency': max(expenses, key=lambda x: x['amount_usd'])['currency'], } - return flask.render_template('finances.html', finances=finances) + transaction_table = [] + + transactions = [{'change': '+', **donation} for donation in donations] + [{'change': '-', **expense} for expense in expenses] + transactions = sorted(transactions, key=lambda x: x['timestamp'], reverse=True) + + for transaction in transactions: + description = '' + + if transaction['change'] == '+': + description = f'Discord/{transaction["user"]}' + + if transaction['change'] == '-': + description = f'{transaction["reason"]} -> {transaction["to"]}' + + if transaction['currency'] in ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'NZD', 'CHF', 'JPY', 'CNY', 'HKD', 'SGD']: + transaction['proof'] = '' + + if transaction['change'] == '-': + transaction['amount_usd'] = -transaction['amount_usd'] + + amount = f'{round(transaction["amount_usd"])}' + + transaction_table.append({ + 'Amount (USD)': amount, + 'Currency': transaction['currency'], + 'Type': transaction.get('type', 'donation'), + 'Description': description, + 'Timestamp': time.strftime('%Y-%m-%d %H:%M', time.localtime(transaction['timestamp'])), + 'Proof': transaction['proof'], + }) + + # convert transaction_table to html + transaction_table = pd.DataFrame(transaction_table).to_html( + index=False, + classes=['table', 'table-striped', 'table-hover'], + table_id='transactionTable' + ) + + return flask.render_template('finances.html', finances=finances, transaction_table=transaction_table) @app.route('/finances/json') def finances_download(): try: data = get_finances() except Exception: - return flask.Response('Error fetching finances from database. This might be cause the data is still being processed. Sorry.', status=500) + return flask.Response('Error fetching finances from database. This might be cause the data is still being processed. Please allow up to a few minutes.', status=500) virtual_file = io.StringIO() json.dump(data, virtual_file, indent=4) diff --git a/web/templates/finances.html b/web/templates/finances.html index c32d60f..499754b 100644 --- a/web/templates/finances.html +++ b/web/templates/finances.html @@ -24,23 +24,47 @@
We have received {{ finances.donations_num }} donations so far, - totaling {{ finances.donations_total }} USD. + totaling ${{ finances.donations_total }}. The largest donation is ${{ finances.donations_max }}.
- The average donation has an amount of {{ finances.donations_avg }} USD. + The average donation has an amount of ${{ finances.donations_avg }}. Most people used {{ finances.most_used_donation_currency }} to donate.
- The largest donation is {{ finances.donations_max }} USD. -
We have spent {{ finances.expenses_total }} USD.
We paid our developers {{ finances.expenses_wages }} USD so far.
We usually pay in {{ finances.most_used_expense_currency }}.
We have spent ${{ finances.expenses_total }} so far, ${{ finances.expenses_wages }} of which are wages to our employees.
Our current balance is ~${{ finances.donations_total - finances.expenses_total }}. + Please note that this is just a rough estimate and not an exact value. Due to transaction fees and price fluctuations, + the actual balance is actually lower. +