ezgg-lan-manager/src/ez_lan_manager/services/AccountingService.py
David Rodenkirchen 30b32a4c02 aiomysql refactor
2024-09-03 14:30:32 +02:00

74 lines
2.7 KiB
Python

import logging
from datetime import datetime
from src.ez_lan_manager.services.DatabaseService import DatabaseService
from src.ez_lan_manager.types.Transaction import Transaction
logger = logging.getLogger(__name__.split(".")[-1])
class InsufficientFundsError(Exception):
pass
class AccountingService:
def __init__(self, db_service: DatabaseService) -> None:
self._db_service = db_service
async def add_balance(self, user_id: int, balance_to_add: int, reference: str) -> int:
await self._db_service.add_transaction(Transaction(
user_id=user_id,
value=balance_to_add,
is_debit=False,
reference=reference,
transaction_date=datetime.now()
))
logger.debug(f"Added balance of {self.make_euro_string_from_int(balance_to_add)} to user with ID {user_id}")
return await self.get_balance(user_id)
async def remove_balance(self, user_id: int, balance_to_remove: int, reference: str) -> int:
current_balance = await self.get_balance(user_id)
if (current_balance - balance_to_remove) < 0:
raise InsufficientFundsError
await self._db_service.add_transaction(Transaction(
user_id=user_id,
value=balance_to_remove,
is_debit=True,
reference=reference,
transaction_date=datetime.now()
))
logger.debug(f"Removed balance of {self.make_euro_string_from_int(balance_to_remove)} to user with ID {user_id}")
return await self.get_balance(user_id)
async def get_balance(self, user_id: int) -> int:
balance_buffer = 0
for transaction in await self._db_service.get_all_transactions_for_user(user_id):
if transaction.is_debit:
balance_buffer -= transaction.value
else:
balance_buffer += transaction.value
return balance_buffer
async def get_transaction_history(self, user_id: int) -> list[Transaction]:
return await self._db_service.get_all_transactions_for_user(user_id)
@staticmethod
def make_euro_string_from_int(cent_int: int) -> str:
""" Internally, all money values are cents as ints. Only when showing them to the user we generate a string. Prevents float inaccuracy. """
as_str = str(cent_int)
if as_str[0] == "-":
is_negative = True
as_str = as_str[1:]
else:
is_negative = False
if len(as_str) == 1:
result = f"0.0{as_str}"
elif len(as_str) == 2:
result = f"0.{as_str}"
else:
result = f"{as_str[:-2]}.{as_str[-2:]}"
if is_negative:
result = f"-{result}"
return result