feature/pricelist add server pagination for balance #17
|
@ -175,8 +175,8 @@ def register(data):
|
|||
allowed_keys = User().serialize().keys()
|
||||
values = {key: value for key, value in data.items() if key in allowed_keys}
|
||||
roles = values.pop("roles", [])
|
||||
if "birthday" in values:
|
||||
values["birthday"] = from_iso_format(values["birthday"]).date()
|
||||
if "birthday" in data:
|
||||
values["birthday"] = from_iso_format(data["birthday"]).date()
|
||||
user = User(**values)
|
||||
set_roles(user, roles)
|
||||
|
||||
|
@ -195,6 +195,8 @@ def register(data):
|
|||
)
|
||||
messageController.send_message(messageController.Message(user, text, subject))
|
||||
|
||||
find_user(user.userid)
|
||||
|
||||
return user
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
# English: Debit -> from account
|
||||
# Credit -> to account
|
||||
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy import func, case, and_
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
from datetime import datetime
|
||||
from werkzeug.exceptions import BadRequest, NotFound, Conflict
|
||||
|
||||
from flaschengeist.database import db
|
||||
from flaschengeist.models.user import User
|
||||
from flaschengeist.models.user import User, _UserAttribute
|
||||
|
||||
from .models import Transaction
|
||||
from . import permissions, BalancePlugin
|
||||
|
@ -38,27 +39,114 @@ 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)
|
||||
def get_balances(start: datetime = None, end: datetime = None, limit=None, offset=None, descending=None, sortBy=None):
|
||||
ferfissimo
commented
Der Ansatz ist cool! NICE 👍 Der Ansatz ist cool! NICE 👍
crimsen
commented
Noch irgendwas hier zu machen? Noch irgendwas hier zu machen?
|
||||
class _User(User):
|
||||
_debit = db.relationship(Transaction, back_populates="sender_", foreign_keys=[Transaction._sender_id])
|
||||
_credit = db.relationship(Transaction, back_populates="receiver_", foreign_keys=[Transaction._receiver_id])
|
||||
|
||||
debit = debit.group_by(Transaction._sender_id).all()
|
||||
credit = credit.group_by(Transaction._receiver_id).all()
|
||||
@hybrid_property
|
||||
def debit(self):
|
||||
return sum([cred.amount for cred in self._debit])
|
||||
|
||||
@debit.expression
|
||||
def debit(cls):
|
||||
a = (
|
||||
db.select(func.sum(Transaction.amount))
|
||||
.where(cls.id_ == Transaction._sender_id, Transaction.amount)
|
||||
.scalar_subquery()
|
||||
)
|
||||
return case([(a, a)], else_=0)
|
||||
|
||||
@hybrid_property
|
||||
def credit(self):
|
||||
return sum([cred.amount for cred in self._credit])
|
||||
|
||||
@credit.expression
|
||||
def credit(cls):
|
||||
b = (
|
||||
db.select(func.sum(Transaction.amount))
|
||||
.where(cls.id_ == Transaction._receiver_id, Transaction.amount)
|
||||
.scalar_subquery()
|
||||
)
|
||||
return case([(b, b)], else_=0)
|
||||
|
||||
@hybrid_property
|
||||
def limit(self):
|
||||
return self.get_attribute("balance_limit", None)
|
||||
|
||||
@limit.expression
|
||||
def limit(cls):
|
||||
return (
|
||||
db.select(_UserAttribute.value)
|
||||
.where(and_(cls.id_ == _UserAttribute.user, _UserAttribute.name == "balance_limit"))
|
||||
.scalar_subquery()
|
||||
)
|
||||
|
||||
def get_debit(self, start: datetime = None, end: datetime = None):
|
||||
if start and end:
|
||||
return sum([deb.amount for deb in self._debit if start <= deb.time and deb.time <= end])
|
||||
if start:
|
||||
return sum([deb.amount for deb in self._dedit if start <= deb.time])
|
||||
if end:
|
||||
return sum([deb.amount for deb in self._dedit if deb.time <= end])
|
||||
return self.debit
|
||||
|
||||
def get_credit(self, start: datetime = None, end: datetime = None):
|
||||
if start and end:
|
||||
return sum([cred.amount for cred in self._credit if start <= cred.time and cred.time <= end])
|
||||
if start:
|
||||
return sum([cred.amount for cred in self._credit if start <= cred.time])
|
||||
if end:
|
||||
return sum([cred.amount for cred in self._credit if cred.time <= end])
|
||||
return self.credit
|
||||
|
||||
query = _User.query
|
||||
|
||||
if start:
|
||||
q1 = query.join(_User._credit).filter(start <= Transaction.time)
|
||||
q2 = query.join(_User._debit).filter(start <= Transaction.time)
|
||||
query = q1.union(q2)
|
||||
if end:
|
||||
q1 = query.join(_User._credit).filter(Transaction.time <= end)
|
||||
q2 = query.join(_User._debit).filter(Transaction.time <= end)
|
||||
query = q1.union(q2)
|
||||
|
||||
if sortBy == "balance":
|
||||
if descending:
|
||||
query = query.order_by((_User.credit - _User.debit).desc(), _User.lastname.asc(), _User.firstname.asc())
|
||||
else:
|
||||
query = query.order_by((_User.credit - _User.debit).asc(), _User.lastname.asc(), _User.firstname.asc())
|
||||
elif sortBy == "limit":
|
||||
if descending:
|
||||
query = query.order_by(_User.limit.desc(), User.lastname.asc(), User.firstname.asc())
|
||||
else:
|
||||
query = query.order_by(_User.limit.asc(), User.lastname.asc(), User.firstname.asc())
|
||||
elif sortBy == "firstname":
|
||||
if descending:
|
||||
query = query.order_by(User.firstname.desc(), User.lastname.desc())
|
||||
else:
|
||||
query = query.order_by(User.firstname.asc(), User.lastname.asc())
|
||||
elif sortBy == "lastname":
|
||||
if descending:
|
||||
query = query.order_by(User.lastname.desc(), User.firstname.desc())
|
||||
else:
|
||||
query = query.order_by(User.lastname.asc(), User.firstname.asc())
|
||||
|
||||
count = None
|
||||
if limit:
|
||||
count = query.count()
|
||||
query = query.limit(limit)
|
||||
if offset:
|
||||
query = query.offset(offset)
|
||||
users = query
|
||||
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
|
||||
|
||||
for user in users:
|
||||
|
||||
all[user.userid] = [user.get_credit(start, end), 0]
|
||||
all[user.userid][1] = user.get_debit(start, end)
|
||||
|
||||
return all, count
|
||||
|
||||
|
||||
def send(sender: User, receiver, amount: float, author: User):
|
||||
|
|
|
@ -110,7 +110,6 @@ def limits(current_session: Session):
|
|||
Returns:
|
||||
JSON encoded array of userid with limit or HTTP-error
|
||||
"""
|
||||
|
||||
users = userController.get_users()
|
||||
if request.method == "GET":
|
||||
ferfissimo
commented
Siehe unten: https://flaschengeist.dev/Flaschengeist/flaschengeist/pulls/17/files#issuecomment-164
|
||||
return jsonify([{"userid": user.userid, "limit": user.get_attribute("balance_limit")} for user in users])
|
||||
|
@ -311,5 +310,14 @@ def get_balances(current_session: Session):
|
|||
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()])
|
||||
limit = request.args.get("limit", type=int)
|
||||
offset = request.args.get("offset", type=int)
|
||||
descending = request.args.get("descending", False, type=bool)
|
||||
sortBy = request.args.get("sortBy", type=str)
|
||||
balances, count = balance_controller.get_balances(limit=limit, offset=offset, descending=descending, sortBy=sortBy)
|
||||
return jsonify(
|
||||
{
|
||||
"balances": [{"userid": u, "credit": v[0], "debit": v[1]} for u, v in balances.items()],
|
||||
"count": count,
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Sieht für mich ziemlich unnötig aus, gibt es einen Grund das hier aufzurufen?
Damit werden gleich Userattributes geupdatet. Ohne diese Funktion, gibt es keine "DN" und es erschien mir einfacher, das einfach damit aufzurufen. (Benutze ich auch in run_flaschengeist ldap_sync)
Allgemein, sollte das eigentlich in einem anderen commit rein.