import os import io import time import json import flask import requests import pandas as pd from dotenv import load_dotenv load_dotenv() # cache get_finances() for 5 minutes def get_finances(): res = requests.get( url=f'{os.environ["CORE_API_URL"]}/finances', headers={ 'Authorization': f'{os.environ["CORE_API_KEY"]}' }, timeout=5 ) res.raise_for_status() return res.json() def register(app): @app.route('/finances') def finances_view(): try: data = get_finances() except Exception as exc: print(exc) 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 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 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'], } 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. Please allow up to a few minutes.', status=500) virtual_file = io.StringIO() json.dump(data, virtual_file, indent=4) name = f'finances-{time.strftime("%Y-%m-%d")}.json' virtual_file.seek(0) return flask.send_file( io.BytesIO(virtual_file.read().encode('utf-8')), mimetype='application/json', as_attachment=True, download_name=name )