mirror of
https://github.com/NovaOSS/nova-web.git
synced 2024-11-25 18:53:58 +01:00
130 lines
4.3 KiB
Python
Executable file
130 lines
4.3 KiB
Python
Executable file
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']
|
|
|
|
try:
|
|
avg = round(sum([i['amount_usd'] for i in donations]) / len(donations), 2)
|
|
except ZeroDivisionError:
|
|
avg = 0
|
|
|
|
try:
|
|
most_donation = max(donations, key=lambda x: x['amount_usd'])['currency']
|
|
except ValueError:
|
|
most_donation = '?'
|
|
|
|
try:
|
|
most_expense = max(expenses, key=lambda x: x['amount_usd'])['currency']
|
|
except ValueError:
|
|
most_expense = '?'
|
|
|
|
try:
|
|
donations_max = round(max([i['amount_usd'] for i in donations]))
|
|
except ValueError:
|
|
donations_max = 0
|
|
|
|
finances = {
|
|
'last_update': data['timestamp'],
|
|
'donations_total': round(sum([i['amount_usd'] for i in donations])),
|
|
'donations_num': len(donations),
|
|
'donations_avg': avg,
|
|
'donations_max': donations_max,
|
|
'most_used_donation_currency': most_donation,
|
|
|
|
'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': most_expense,
|
|
}
|
|
|
|
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
|
|
)
|