From 1246ce50fd4e779c4b20a077fdd3a122084ba750 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Fri, 29 Jan 2021 23:28:43 +0100 Subject: [PATCH] [Plugin] Balance: Route and method to query all balances. --- flaschengeist/plugins/balance/__init__.py | 17 +++++++++++++++ .../plugins/balance/balance_controller.py | 21 +++++++++++++++++++ flaschengeist/plugins/balance/models.py | 14 +++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/flaschengeist/plugins/balance/__init__.py b/flaschengeist/plugins/balance/__init__.py index f67e924..c64ca0b 100644 --- a/flaschengeist/plugins/balance/__init__.py +++ b/flaschengeist/plugins/balance/__init__.py @@ -291,3 +291,20 @@ def reverse_transaction(transaction_id, current_session: Session): reversal = balance_controller.reverse_transaction(transaction, current_session._user) return HTTP.created(reversal) 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()]) diff --git a/flaschengeist/plugins/balance/balance_controller.py b/flaschengeist/plugins/balance/balance_controller.py index 35050ff..f363855 100644 --- a/flaschengeist/plugins/balance/balance_controller.py +++ b/flaschengeist/plugins/balance/balance_controller.py @@ -39,6 +39,27 @@ def get_balance(user, start: datetime = None, end: datetime = None): 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): """Send credit from one user to an other diff --git a/flaschengeist/plugins/balance/models.py b/flaschengeist/plugins/balance/models.py index e981ad9..03ab890 100644 --- a/flaschengeist/plugins/balance/models.py +++ b/flaschengeist/plugins/balance/models.py @@ -1,6 +1,8 @@ from datetime import datetime from typing import Optional +from sqlalchemy.ext.hybrid import hybrid_property + from flaschengeist.database import db from flaschengeist.models.user import User from flaschengeist.models import ModelSerializeMixin, UtcDateTime @@ -31,14 +33,22 @@ class Transaction(db.Model, ModelSerializeMixin): author_: User = db.relationship("User", foreign_keys=[_author_id]) original_ = db.relationship("Transaction", uselist=False, backref=db.backref("reversal_", remote_side=[id])) - @property + @hybrid_property def sender_id(self): 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): 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 def author_id(self): return self.author_.userid