mirror of
https://github.com/DarkflameUniverse/NexusDashboard.git
synced 2024-08-30 18:12:11 +00:00
Fix reports
Add currency report make reports use json storage Make tables nicer
This commit is contained in:
parent
1a5531eb19
commit
b2af6d967a
@ -981,14 +981,21 @@ class Server(db.Model):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
class ItemReports(db.Model):
|
class Reports(db.Model):
|
||||||
__tablename__ = 'item_reports'
|
__tablename__ = 'reports'
|
||||||
|
|
||||||
data = db.Column(
|
data = db.Column(
|
||||||
JSON(),
|
JSON(),
|
||||||
nullable=False
|
nullable=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
report_type = db.Column(
|
||||||
|
db.VARCHAR(35),
|
||||||
|
nullable=False,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=False
|
||||||
|
)
|
||||||
|
|
||||||
date = db.Column(
|
date = db.Column(
|
||||||
db.Date(),
|
db.Date(),
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
|
120
app/reports.py
120
app/reports.py
@ -1,8 +1,8 @@
|
|||||||
from flask import render_template, Blueprint, redirect, url_for, request, abort, flash, request
|
from flask import render_template, Blueprint, redirect, url_for, request, abort, flash, request
|
||||||
from flask_user import login_required, current_user
|
from flask_user import login_required, current_user
|
||||||
from app.models import db, CharacterInfo, Account, CharacterXML, ItemReports
|
from app.models import db, CharacterInfo, Account, CharacterXML, Reports
|
||||||
from app import gm_level, scheduler
|
from app import gm_level, scheduler
|
||||||
import datetime, xmltodict
|
import datetime, xmltodict, json
|
||||||
|
|
||||||
reports_blueprint = Blueprint('reports', __name__)
|
reports_blueprint = Blueprint('reports', __name__)
|
||||||
|
|
||||||
@ -10,49 +10,103 @@ reports_blueprint = Blueprint('reports', __name__)
|
|||||||
@login_required
|
@login_required
|
||||||
@gm_level(3)
|
@gm_level(3)
|
||||||
def index():
|
def index():
|
||||||
items = ItemReports.query.distinct(ItemReports.date).group_by(ItemReports.date).all()
|
reports = Reports.query.distinct(Reports.date).group_by(Reports.date).all()
|
||||||
|
print(gen_item_report())
|
||||||
return render_template('reports/index.html.j2', items=items)
|
print(gen_currency_report())
|
||||||
|
return render_template('reports/index.html.j2', reports=reports)
|
||||||
|
|
||||||
@reports_blueprint.route('/items/by_date/<date>', methods=['GET', 'POST'])
|
@reports_blueprint.route('/items/by_date/<date>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@gm_level(3)
|
@gm_level(3)
|
||||||
def items_by_date(date):
|
def items_by_date(date):
|
||||||
items = ItemReports.query.filter(ItemReports.date==date).order_by(ItemReports.count.desc()).all()
|
data = Reports.query.filter(Reports.date==date).filter(Reports.report_type=="items").first().data
|
||||||
return render_template('reports/items/by_date.html.j2', items=items, date=date)
|
return render_template('reports/items/by_date.html.j2', data=data, date=date)
|
||||||
|
|
||||||
|
@reports_blueprint.route('/currency/by_date/<date>', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
@gm_level(3)
|
||||||
|
def currency_by_date(date):
|
||||||
|
data = Reports.query.filter(Reports.date==date).filter(Reports.report_type=="currency").first().data
|
||||||
|
return render_template('reports/currency/by_date.html.j2', data=data, date=date)
|
||||||
|
|
||||||
|
|
||||||
@scheduler.task("cron", id="gen_item_report", hour=7)
|
@scheduler.task("cron", id="gen_item_report", hour=23)
|
||||||
def gen_item_report():
|
def gen_item_report():
|
||||||
date = datetime.date.today().strftime('%Y-%m-%d')
|
with scheduler.app.app_context():
|
||||||
report = ItemReports.query.filter(ItemReports.date==date).first()
|
date = datetime.date.today().strftime('%Y-%m-%d')
|
||||||
|
report = Reports.query.filter(Reports.date==date).filter(Reports.report_type=="items").first()
|
||||||
|
|
||||||
# Only one report per day
|
# Only one report per day
|
||||||
if report != None:
|
if report != None:
|
||||||
return f"Report Already Generated for {date}"
|
return f"Item Report Already Generated for {date}"
|
||||||
|
|
||||||
char_xmls = CharacterXML.query.join(
|
char_xmls = CharacterXML.query.join(
|
||||||
CharacterInfo,
|
CharacterInfo,
|
||||||
CharacterInfo.id==CharacterXML.id
|
CharacterInfo.id==CharacterXML.id
|
||||||
).join(
|
).join(
|
||||||
Account,
|
Account,
|
||||||
CharacterInfo.account_id==Account.id
|
CharacterInfo.account_id==Account.id
|
||||||
).filter(Account.gm_level < 3).all()
|
).filter(Account.gm_level < 3).all()
|
||||||
|
|
||||||
report_data={}
|
report_data={}
|
||||||
|
|
||||||
for char_xml in char_xmls:
|
for char_xml in char_xmls:
|
||||||
character_json = xmltodict.parse(
|
character_json = xmltodict.parse(
|
||||||
char_xml.xml_data,
|
char_xml.xml_data,
|
||||||
attr_prefix="attr_"
|
attr_prefix="attr_"
|
||||||
|
)
|
||||||
|
for inv in character_json["obj"]["inv"]["items"]["in"]:
|
||||||
|
if "i" in inv.keys() and type(inv["i"]) == list and (int(inv["attr_t"])==0 or int(inv["attr_t"])==0):
|
||||||
|
for item in inv["i"]:
|
||||||
|
if item["attr_l"] in report_data:
|
||||||
|
report_data[item["attr_l"]] = report_data[item["attr_l"]] + int(item["attr_c"])
|
||||||
|
else:
|
||||||
|
report_data[item["attr_l"]] = int(item["attr_c"])
|
||||||
|
|
||||||
|
new_report = Reports(
|
||||||
|
data=report_data,
|
||||||
|
report_type="items",
|
||||||
|
date=date
|
||||||
)
|
)
|
||||||
for inv in character_json["obj"]["inv"]["items"]["in"]:
|
|
||||||
if "i" in inv.keys() and type(inv["i"]) == list and (int(inv["attr_t"])==0 or int(inv["attr_t"])==0):
|
new_report.save()
|
||||||
for item in inv["i"]:
|
|
||||||
if item["attr_l"] in report_data:
|
return f"Generated Item Report for {date}"
|
||||||
report_data[item["attr_l"]] = report_data[item["attr_l"]] + int(item["attr_c"])
|
|
||||||
else:
|
|
||||||
report_data[item["attr_l"]] = int(item["attr_c"])
|
|
||||||
|
|
||||||
|
|
||||||
return f"Generated Report for {date}"
|
@scheduler.task("cron", id="gen_currency_report", hour=23)
|
||||||
|
def gen_currency_report():
|
||||||
|
with scheduler.app.app_context():
|
||||||
|
date = datetime.date.today().strftime('%Y-%m-%d')
|
||||||
|
report = Reports.query.filter(Reports.date==date).filter(Reports.report_type=="currency").first()
|
||||||
|
|
||||||
|
# Only one report per day
|
||||||
|
if report != None:
|
||||||
|
return f"Currency Report Already Generated for {date}"
|
||||||
|
|
||||||
|
characters = CharacterXML.query.join(
|
||||||
|
CharacterInfo,
|
||||||
|
CharacterInfo.id==CharacterXML.id
|
||||||
|
).join(
|
||||||
|
Account,
|
||||||
|
CharacterInfo.account_id==Account.id
|
||||||
|
).filter(Account.gm_level < 3).all()
|
||||||
|
|
||||||
|
report_data={}
|
||||||
|
|
||||||
|
for character in characters:
|
||||||
|
character_json = xmltodict.parse(
|
||||||
|
character.xml_data,
|
||||||
|
attr_prefix="attr_"
|
||||||
|
)
|
||||||
|
report_data[CharacterInfo.query.filter(CharacterInfo.id==character.id).first().name] = int(character_json["obj"]["char"]["attr_cc"])
|
||||||
|
|
||||||
|
new_report = Reports(
|
||||||
|
data=report_data,
|
||||||
|
report_type="currency",
|
||||||
|
date=date
|
||||||
|
)
|
||||||
|
|
||||||
|
new_report.save()
|
||||||
|
|
||||||
|
return f"Generated Currency Report for {date}"
|
||||||
|
@ -8,7 +8,7 @@ $theme-colors: (
|
|||||||
$link-color: #005ac2;
|
$link-color: #005ac2;
|
||||||
|
|
||||||
@import "../bootstrap-4.2.1/scss/bootstrap";
|
@import "../bootstrap-4.2.1/scss/bootstrap";
|
||||||
@import url(http://fonts.googleapis.com/css?family=Nunito:700);
|
@import url(https://fonts.googleapis.com/css?family=Nunito:700);
|
||||||
|
|
||||||
body { font-family:'Nunito', Helvetica, Arial, sans-serif; }
|
body { font-family:'Nunito', Helvetica, Arial, sans-serif; }
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{% endblock content_before %}
|
{% endblock content_before %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<table class="table" id="accounts_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="accounts_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{% endblock content_before %}
|
{% endblock content_before %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<table class="table" id="accounts_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="accounts_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table" id="characters_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="characters_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if current_user.is_authenticated and current_user.gm_level >= 2 %}
|
{% if current_user.is_authenticated and current_user.gm_level >= 2 %}
|
||||||
|
<a id='report-index' class='nav-link' href='{{ url_for('reports.index') }}'>Reports</a>
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Tools</a>
|
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Tools</a>
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table" id="command_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="command_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table" id="activity_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="activity_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
@ -49,10 +49,10 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-right">
|
<div class="col text-right">
|
||||||
TODO: add more Contributors
|
Developer:
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Add more
|
Jett.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -62,7 +62,7 @@
|
|||||||
Source
|
Source
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a href="https://github.com/DarkflameUniverse/AccountManager">
|
<a href="https://github.com/DarkflameUniverse/NexusDashboard">
|
||||||
Github
|
Github
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h4> Characters </h4>
|
<h4> Characters </h4>
|
||||||
<hr class="bg-primary"/>
|
<hr class="bg-primary"/>
|
||||||
<table class="table" id="character_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="character_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<h4> Pets </h4>
|
<h4> Pets </h4>
|
||||||
<hr class="bg-primary"/>
|
<hr class="bg-primary"/>
|
||||||
<table class="table" id="pet_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="pet_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<h4> Properties </h4>
|
<h4> Properties </h4>
|
||||||
<hr class="bg-primary"/>
|
<hr class="bg-primary"/>
|
||||||
<table class="table" id="property_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="property_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
Bulk Create Play Keys
|
Bulk Create Play Keys
|
||||||
</a>
|
</a>
|
||||||
<hr class="bg-primary"/>
|
<hr class="bg-primary"/>
|
||||||
<table class="table" id="play_key_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="play_key_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table" id="properties_table">
|
<table class="table table-dark table-striped table-bordered table-hover" id="properties_table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
|
51
app/templates/reports/currency/by_date.html.j2
Normal file
51
app/templates/reports/currency/by_date.html.j2
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{% extends 'base.html.j2' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Currency on {{ date }}
|
||||||
|
{% endblock title %}
|
||||||
|
|
||||||
|
{% block content_before %}
|
||||||
|
Currency on {{ date }}
|
||||||
|
{% endblock content_before %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='table-responsive'>
|
||||||
|
<table class="table table-dark table-striped table-bordered table-hover"
|
||||||
|
id="currency_by_date"
|
||||||
|
data-order='[[ 1, "desc" ]]'>
|
||||||
|
<thead>
|
||||||
|
<th scope="col">
|
||||||
|
Character
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
currency
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for name, currency in data.items() %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ currency }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{{ super () }}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
let currency_by_date = $('#currency_by_date').DataTable({
|
||||||
|
"processing": false,
|
||||||
|
"serverSide": false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -12,14 +12,21 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
Items: <br/>
|
Items: <br/>
|
||||||
{% for item in items %}
|
{% for report in reports %}
|
||||||
<a role="button" class="btn btn-primary btn btn-block"
|
<a role="button" class="btn btn-primary btn btn-block"
|
||||||
href='{{url_for('reports.items_by_date', date=item.date)}}'>
|
href='{{url_for('reports.items_by_date', date=report.date)}}'>
|
||||||
{{item.date}}
|
{{report.date}}
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
Currency: <br/>
|
||||||
|
{% for report in reports %}
|
||||||
|
<a role="button" class="btn btn-primary btn btn-block"
|
||||||
|
href='{{url_for('reports.currency_by_date', date=report.date)}}'>
|
||||||
|
{{report.date}}
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class='table-responsive'>
|
<div class='table-responsive'>
|
||||||
<table class="table table-dark table-striped table-bordered table-hover"
|
<table class="table table-dark table-striped table-bordered table-hover"
|
||||||
id="two_weeks"
|
id="items_by_date"
|
||||||
data-order='[[ 1, "asc" ]]'
|
data-order='[[ 1, "desc" ]]'>
|
||||||
data-page-length='25'>
|
|
||||||
<thead>
|
<thead>
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
Item
|
Item
|
||||||
@ -26,16 +25,16 @@
|
|||||||
</th>
|
</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in items %}
|
{% for lot, count in data.items() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{{ item.item|get_lot_name }}
|
{{ lot|get_lot_name }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ item.count }}
|
{{ count }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ item.item|get_lot_rarity }}
|
{{ lot|get_lot_rarity }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -44,3 +43,14 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{{ super () }}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
let items_by_date = $('#items_by_date').DataTable({
|
||||||
|
"processing": false,
|
||||||
|
"serverSide": false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
"""items-reports
|
"""reports
|
||||||
|
|
||||||
Revision ID: 3da561e7f7c0
|
Revision ID: aee4c6c24811
|
||||||
Revises: 8a2966b9f7ee
|
Revises: 8a2966b9f7ee
|
||||||
Create Date: 2022-01-16 18:27:11.067205
|
Create Date: 2022-01-16 20:12:39.816567
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from alembic import op
|
from alembic import op
|
||||||
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '3da561e7f7c0'
|
revision = 'aee4c6c24811'
|
||||||
down_revision = '8a2966b9f7ee'
|
down_revision = '8a2966b9f7ee'
|
||||||
branch_labels = None
|
branch_labels = None
|
||||||
depends_on = None
|
depends_on = None
|
||||||
@ -18,15 +18,16 @@ depends_on = None
|
|||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('item_reports',
|
op.create_table('reports',
|
||||||
sa.Column('data', sa.JSON(), nullable=False),
|
sa.Column('data', sa.JSON(), nullable=False),
|
||||||
|
sa.Column('report_type', sa.VARCHAR(length=35), autoincrement=False, nullable=False),
|
||||||
sa.Column('date', sa.Date(), autoincrement=False, nullable=False),
|
sa.Column('date', sa.Date(), autoincrement=False, nullable=False),
|
||||||
sa.PrimaryKeyConstraint('date')
|
sa.PrimaryKeyConstraint('report_type', 'date')
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('item_reports')
|
op.drop_table('reports')
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user