fix floor transaction with value which has more ziffers than scale #33

This commit is contained in:
Tim Gröger 2023-05-17 14:47:40 +02:00
parent b40d40644d
commit cab172dc65
3 changed files with 65 additions and 10 deletions

View File

@ -48,7 +48,13 @@ def get_balance(user, start: datetime = None, end: datetime = None):
def get_balances(
start: datetime = None, end: datetime = None, limit=None, offset=None, descending=None, sortBy=None, _filter=None
start: datetime = None,
end: datetime = None,
limit=None,
offset=None,
descending=None,
sortBy=None,
_filter=None,
):
logger.debug(
f"get_balances(start={start}, end={end}, limit={limit}, offset={offset}, descending={descending}, sortBy={sortBy}, _filter={_filter})"
@ -56,7 +62,11 @@ def get_balances(
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])
_credit = db.relationship(
Transaction,
back_populates="receiver_",
foreign_keys=[Transaction._receiver_id],
)
@hybrid_property
def debit(self):
@ -92,7 +102,12 @@ def get_balances(
def limit(cls):
return (
db.select(_UserAttribute.value)
.where(and_(cls.id_ == _UserAttribute.user, _UserAttribute.name == "balance_limit"))
.where(
and_(
cls.id_ == _UserAttribute.user,
_UserAttribute.name == "balance_limit",
)
)
.scalar_subquery()
)
@ -127,14 +142,25 @@ def get_balances(
if _filter:
query = query.filter(
or_(_User.firstname.ilike(f"%{_filter.lower()}%"), _User.lastname.ilike(f"%{_filter.lower()}%"))
or_(
_User.firstname.ilike(f"%{_filter.lower()}%"),
_User.lastname.ilike(f"%{_filter.lower()}%"),
)
)
if sortBy == "balance":
if descending:
query = query.order_by((_User.credit - _User.debit).desc(), _User.lastname.asc(), _User.firstname.asc())
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())
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())
@ -209,7 +235,11 @@ def send(sender: User, receiver, amount: float, author: User):
BalancePlugin.getPlugin().notify(
sender,
"Neue Transaktion",
{"type": NotifyType.SUB_FROM, "author_id": author.userid, "amount": amount},
{
"type": NotifyType.SUB_FROM,
"author_id": author.userid,
"amount": amount,
},
)
if receiver is not None and receiver.id_ != author.id_:
if sender is not None:
@ -226,7 +256,11 @@ def send(sender: User, receiver, amount: float, author: User):
BalancePlugin.getPlugin().notify(
receiver,
"Neue Transaktion",
{"type": NotifyType.ADD_FROM, "author_id": author.userid, "amount": amount},
{
"type": NotifyType.ADD_FROM,
"author_id": author.userid,
"amount": amount,
},
)
return transaction

View File

@ -1,7 +1,9 @@
from datetime import datetime
from typing import Optional
from sqlalchemy.ext.hybrid import hybrid_property
from math import floor
from flaschengeist import logger
from flaschengeist.database import db
from flaschengeist.models.user import User
from flaschengeist.models import ModelSerializeMixin, UtcDateTime, Serial
@ -18,8 +20,9 @@ class Transaction(db.Model, ModelSerializeMixin):
# Public and exported member
id: int = db.Column("id", Serial, primary_key=True)
time: datetime = db.Column(UtcDateTime, nullable=False, default=UtcDateTime.current_utc)
amount: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False), nullable=False)
_amount: float = db.Column("amount", db.Numeric(precision=5, scale=2, asdecimal=False), nullable=False)
reversal_id: Optional[int] = db.Column(Serial, db.ForeignKey("balance_transaction.id"))
amount: float
# Dummy properties used for JSON serialization (userid instead of full user)
author_id: Optional[str] = None
@ -56,3 +59,14 @@ class Transaction(db.Model, ModelSerializeMixin):
@property
def original_id(self):
return self.original_.id if self.original_ else None
@property
def amount(self):
return self._amount
@amount.setter
def amount(self, value):
self._amount = floor(value * 100) / 100
def __repr__(self):
return f"<Transaction {self.id} {self.amount} {self.time} {self.sender_id} {self.receiver_id} {self.author_id}>"

View File

@ -1,4 +1,5 @@
from datetime import datetime, timezone
from logging import log
from werkzeug.exceptions import Forbidden, BadRequest
from flask import Blueprint, request, jsonify
@ -163,6 +164,7 @@ def get_balance(userid, current_session: Session):
end = datetime.now(tz=timezone.utc)
balance = balance_controller.get_balance(user, start, end)
logger.debug(f"Balance of {user.userid} from {start} to {end}: {balance}")
return {"credit": balance[0], "debit": balance[1], "balance": balance[2]}
@ -224,6 +226,7 @@ def get_transactions(userid, current_session: Session):
show_cancelled=show_cancelled,
descending=descending,
)
logger.debug(f"transactions: {transactions}")
return {"transactions": transactions, "count": count}
@ -321,7 +324,11 @@ def get_balances(current_session: Session):
_filter = request.args.get("filter", None, type=str)
logger.debug(f"request.args: {request.args}")
balances, count = balance_controller.get_balances(
limit=limit, offset=offset, descending=descending, sortBy=sortBy, _filter=_filter
limit=limit,
offset=offset,
descending=descending,
sortBy=sortBy,
_filter=_filter,
)
return jsonify(
{