add admin summary view, fix product id calculation
parent
ef71d8732a
commit
e4d7404a45
|
@ -10,11 +10,13 @@ from flask import (
|
||||||
url_for,
|
url_for,
|
||||||
session,
|
session,
|
||||||
abort,
|
abort,
|
||||||
|
current_app,
|
||||||
)
|
)
|
||||||
from flask_login import current_user, fresh_login_required
|
from flask_login import current_user, fresh_login_required
|
||||||
|
|
||||||
from bitvend import dev, spaceauth
|
from bitvend import dev, spaceauth
|
||||||
from bitvend.models import db, Transaction
|
from bitvend.models import db, Transaction
|
||||||
|
from sqlalchemy import func
|
||||||
from bitvend.forms import ManualForm
|
from bitvend.forms import ManualForm
|
||||||
from spaceauth import cap_required
|
from spaceauth import cap_required
|
||||||
|
|
||||||
|
@ -25,7 +27,8 @@ def get_user_groups():
|
||||||
groups_ts = session.get("groups_ts", 0)
|
groups_ts = session.get("groups_ts", 0)
|
||||||
|
|
||||||
if not groups or groups_uid != current_user.uid or time.time() - groups_ts >= 60.0:
|
if not groups or groups_uid != current_user.uid or time.time() - groups_ts >= 60.0:
|
||||||
groups = spaceauth.remote.get("/api/1/userinfo").data.get("groups")
|
resp = spaceauth.remote.get("/api/1/userinfo")
|
||||||
|
groups = resp.data.get("groups")
|
||||||
|
|
||||||
session["groups"] = groups
|
session["groups"] = groups
|
||||||
session["groups_ts"] = time.time()
|
session["groups_ts"] = time.time()
|
||||||
|
@ -39,6 +42,9 @@ def admin_required(fn):
|
||||||
@wraps(fn)
|
@wraps(fn)
|
||||||
def wrapped(*args, **kwargs):
|
def wrapped(*args, **kwargs):
|
||||||
groups = get_user_groups()
|
groups = get_user_groups()
|
||||||
|
if not groups:
|
||||||
|
return current_app.login_manager.unauthorized()
|
||||||
|
|
||||||
if "vending-admin" not in groups:
|
if "vending-admin" not in groups:
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
@ -50,7 +56,14 @@ def admin_required(fn):
|
||||||
bp = Blueprint("admin", __name__)
|
bp = Blueprint("admin", __name__)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/manual", methods=["GET", "POST"])
|
@bp.route("/")
|
||||||
|
@fresh_login_required
|
||||||
|
@admin_required
|
||||||
|
def admin_index():
|
||||||
|
return redirect(url_for("admin.manual"))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/manual/", methods=["GET", "POST"])
|
||||||
@fresh_login_required
|
@fresh_login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
def manual():
|
def manual():
|
||||||
|
@ -60,7 +73,13 @@ def manual():
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("Operation successful.", "success")
|
flash("Operation successful.", "success")
|
||||||
|
|
||||||
return render_template("admin/manual.html", form=form)
|
return render_template(
|
||||||
|
"admin/manual.html",
|
||||||
|
form=form,
|
||||||
|
summary=db.session.query(func.sum(Transaction.amount))
|
||||||
|
.filter(Transaction.uid != "__bitcoin__")
|
||||||
|
.scalar(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/transactions/", defaults={"page": 1})
|
@bp.route("/transactions/", defaults={"page": 1})
|
||||||
|
|
|
@ -31,7 +31,7 @@ class BitvendCashlessMDBDevice(CashlessMDBDevice):
|
||||||
if self.current_tx_id:
|
if self.current_tx_id:
|
||||||
with self.app.app_context():
|
with self.app.app_context():
|
||||||
tx = Transaction.query.get(self.current_tx_id)
|
tx = Transaction.query.get(self.current_tx_id)
|
||||||
tx.product_id = product
|
tx.product_id = product + 9
|
||||||
tx.product_value = value
|
tx.product_value = value
|
||||||
|
|
||||||
if tx.amount is None:
|
if tx.amount is None:
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="list-group">
|
||||||
|
{% macro link(endpoint) %}<a href="{{ url_for(endpoint) }}" class="list-group-item{% if request.endpoint == endpoint %} active{%endif %}">{{ caller() }}</a>{% endmacro %}
|
||||||
|
{% call link('admin.manual') %}Dashboard{% endcall %}
|
||||||
|
{% call link('admin.transactions') %}Transactions{% endcall %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-10">{% block content %}{% endblock %}</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,9 +1,17 @@
|
||||||
{% extends "base.html" %}
|
{% extends "admin/base.html" %}
|
||||||
|
|
||||||
{% from "_helpers.html" import render_field, render_submit %}
|
{% from "_helpers.html" import render_field, render_submit, format_currency %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 class="page-header">Manual transaction </h1>
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="well text-right">
|
||||||
|
<h3><small class="pull-left">Cash summary</small> {{ format_currency(summary) }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 class="page-header">Manual transaction</h1>
|
||||||
<p class="text-muted">Creates manual transaction for current user. Use this when filling machine with money.</p>
|
<p class="text-muted">Creates manual transaction for current user. Use this when filling machine with money.</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<form action="{{ url_for('.manual') }}" method="POST" class="form-horizontal col-md-6 col-md-offset-3">
|
<form action="{{ url_for('.manual') }}" method="POST" class="form-horizontal col-md-6 col-md-offset-3">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base.html" %}
|
{% extends "admin/base.html" %}
|
||||||
|
|
||||||
{% from "_helpers.html" import format_currency, render_pagination %}
|
{% from "_helpers.html" import format_currency, render_pagination %}
|
||||||
{% set _tx_styles = {
|
{% set _tx_styles = {
|
||||||
|
|
|
@ -85,7 +85,10 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
{% block body %}
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
{% endblock %}
|
||||||
<hr>
|
<hr>
|
||||||
<footer class="row"><big>made by <a href="https://wiki.hackerspace.pl/people:informatic:start">inf</a></big>
|
<footer class="row"><big>made by <a href="https://wiki.hackerspace.pl/people:informatic:start">inf</a></big>
|
||||||
<span class="pull-right text-right">1infuHrvt7tuGY8nJcfTwB3wwAR1XwUcW • <a href="https://code.hackerspace.pl/informatic/bitvend">sauce</a><br />report any issues to <a href="mailto:informatic@hackerspace.pl">informatic@hackerspace.pl</a></span>
|
<span class="pull-right text-right">1infuHrvt7tuGY8nJcfTwB3wwAR1XwUcW • <a href="https://code.hackerspace.pl/informatic/bitvend">sauce</a><br />report any issues to <a href="mailto:informatic@hackerspace.pl">informatic@hackerspace.pl</a></span>
|
||||||
|
|
|
@ -220,10 +220,9 @@ class CashlessMDBDevice(MDBDevice):
|
||||||
elif req.command == CASHLESS_VEND:
|
elif req.command == CASHLESS_VEND:
|
||||||
if req.data[0] == 0x00: # vend request
|
if req.data[0] == 0x00: # vend request
|
||||||
self.logger.info("VEND: request %r", req)
|
self.logger.info("VEND: request %r", req)
|
||||||
value, product_bcd = struct.unpack(">xhhx", req.data)
|
value, product = struct.unpack(">xhhx", req.data)
|
||||||
product = bcd_decode(product_bcd)
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
"VEND: requested %d (%04x) for %d", product, product_bcd, value
|
"VEND: requested %d (%04x) for %d", product, product, value
|
||||||
)
|
)
|
||||||
if self.vend_request(product, value):
|
if self.vend_request(product, value):
|
||||||
# accept. two latter bytes are value subtracted from balance
|
# accept. two latter bytes are value subtracted from balance
|
||||||
|
|
Loading…
Reference in New Issue