[Plugin] Balance: Route and method to query all balances.

This commit is contained in:
Ferdinand Thiessen 2021-01-29 23:28:43 +01:00
parent b46e93fd26
commit 1246ce50fd
3 changed files with 50 additions and 2 deletions

View File

@ -291,3 +291,20 @@ def reverse_transaction(transaction_id, current_session: Session):
reversal = balance_controller.reverse_transaction(transaction, current_session._user) reversal = balance_controller.reverse_transaction(transaction, current_session._user)
return HTTP.created(reversal) return HTTP.created(reversal)
raise Forbidden raise Forbidden
@balance_bp.route("/balance", methods=["GET"])
@login_required(permission=permissions.SHOW_OTHER)
def get_balances(current_session: Session):
"""Get all balances
Route: ``/balance`` | Method: ``GET``
Args:
current_session: Session sent with Authorization Header
Returns:
JSON Array containing credit, debit and userid for each user or HTTP error
"""
balances = balance_controller.get_balances()
return jsonify([{"userid": u, "credit": v[0], "debit": v[1]} for u, v in balances.items()])

View File

@ -39,6 +39,27 @@ def get_balance(user, start: datetime = None, end: datetime = None):
return credit, debit, credit - debit return credit, debit, credit - debit
def get_balances(start: datetime = None, end: datetime = None):
debit = db.session.query(Transaction.sender_id, func.sum(Transaction.amount)).filter(Transaction.sender_ != None)
credit = db.session.query(Transaction.receiver_id, func.sum(Transaction.amount)).filter(Transaction.receiver_ != None)
if start:
debit = debit.filter(start <= Transaction.time)
credit = credit.filter(start <= Transaction.time)
if end:
debit = debit.filter(Transaction.time <= end)
credit = credit.filter(Transaction.time <= end)
debit = debit.group_by(Transaction._sender_id).all()
credit = credit.group_by(Transaction._receiver_id).all()
all = {}
for uid, cred in credit:
all[uid] = [cred, 0]
for uid, deb in debit:
all.setdefault(uid, [0, 0])
all[uid][1] = deb
return all
def send(sender: User, receiver, amount: float, author: User): def send(sender: User, receiver, amount: float, author: User):
"""Send credit from one user to an other """Send credit from one user to an other

View File

@ -1,6 +1,8 @@
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from sqlalchemy.ext.hybrid import hybrid_property
from flaschengeist.database import db from flaschengeist.database import db
from flaschengeist.models.user import User from flaschengeist.models.user import User
from flaschengeist.models import ModelSerializeMixin, UtcDateTime from flaschengeist.models import ModelSerializeMixin, UtcDateTime
@ -31,14 +33,22 @@ class Transaction(db.Model, ModelSerializeMixin):
author_: User = db.relationship("User", foreign_keys=[_author_id]) author_: User = db.relationship("User", foreign_keys=[_author_id])
original_ = db.relationship("Transaction", uselist=False, backref=db.backref("reversal_", remote_side=[id])) original_ = db.relationship("Transaction", uselist=False, backref=db.backref("reversal_", remote_side=[id]))
@property @hybrid_property
def sender_id(self): def sender_id(self):
return self.sender_.userid if self.sender_ else None return self.sender_.userid if self.sender_ else None
@property @sender_id.expression
def sender_id(cls):
return db.select([User.userid]).where(cls._sender_id == User._id).as_scalar()
@hybrid_property
def receiver_id(self): def receiver_id(self):
return self.receiver_.userid if self.receiver_ else None return self.receiver_.userid if self.receiver_ else None
@receiver_id.expression
def receiver_id(cls):
return db.select([User.userid]).where(cls._receiver_id == User._id).as_scalar()
@property @property
def author_id(self): def author_id(self):
return self.author_.userid return self.author_.userid