add ticketing service
This commit is contained in:
parent
b1bd1b11b5
commit
96278258ef
@ -11,6 +11,7 @@ from random import randint
|
||||
|
||||
from src.ez_lan_manager.services.MailingService import MailingService
|
||||
from src.ez_lan_manager.services.NewsService import NewsService
|
||||
from src.ez_lan_manager.services.TicketingService import TicketingService
|
||||
from src.ez_lan_manager.services.UserService import UserService
|
||||
from src.ez_lan_manager.types.News import News
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
@ -21,13 +22,17 @@ logger = logging.getLogger(__name__.split(".")[-1])
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
configuration_service = ConfigurationService(from_root("config.toml"))
|
||||
lan_info = configuration_service.get_lan_info()
|
||||
db_config = configuration_service.get_database_configuration()
|
||||
db_service = DatabaseService(db_config)
|
||||
user_service = UserService(db_service)
|
||||
accounting_service = AccountingService(db_service)
|
||||
news_service = NewsService(db_service)
|
||||
mailing_service = MailingService(configuration_service.get_mailing_service_configuration())
|
||||
#mailing_service.send_email("Hallo von EZ LAN Mananger", "Grüße :)", "davidr.develop@gmail.com")
|
||||
ticketing_service = TicketingService(lan_info, db_service, accounting_service)
|
||||
|
||||
print(ticketing_service.refund_ticket(19))
|
||||
#print(ticketing_service.get_available_tickets())
|
||||
|
||||
|
||||
#user_service.create_user("Alex", "alex@gmail.com", "MeinPasswort")
|
||||
|
||||
@ -8,6 +8,7 @@ from mariadb import Cursor
|
||||
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import DatabaseConfiguration
|
||||
from src.ez_lan_manager.types.News import News
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
from src.ez_lan_manager.types.Transaction import Transaction
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
@ -178,3 +179,75 @@ class DatabaseService:
|
||||
))
|
||||
|
||||
return results
|
||||
|
||||
def get_tickets(self) -> list[Ticket]:
|
||||
results = []
|
||||
cursor = self._get_cursor()
|
||||
try:
|
||||
cursor.execute("SELECT * FROM tickets INNER JOIN users ON tickets.user = users.user_id;", ())
|
||||
except Exception as e:
|
||||
logger.warning(f"Error fetching tickets: {e}")
|
||||
return []
|
||||
|
||||
for ticket_raw in cursor.fetchall():
|
||||
user = self._map_db_result_to_user(ticket_raw[3:])
|
||||
results.append(Ticket(
|
||||
ticket_id=ticket_raw[0],
|
||||
category=ticket_raw[1],
|
||||
purchase_date=ticket_raw[3],
|
||||
owner=user
|
||||
))
|
||||
|
||||
return results
|
||||
|
||||
def get_ticket_for_user(self, user_id: int) -> Optional[Ticket]:
|
||||
cursor = self._get_cursor()
|
||||
try:
|
||||
cursor.execute("SELECT * FROM tickets INNER JOIN users ON tickets.user = users.user_id WHERE user_id=?;", (user_id, ))
|
||||
except Exception as e:
|
||||
logger.warning(f"Error fetching ticket for user: {e}")
|
||||
return
|
||||
|
||||
result = cursor.fetchone()
|
||||
if not result:
|
||||
return
|
||||
|
||||
user = self._map_db_result_to_user(result[3:])
|
||||
return Ticket(
|
||||
ticket_id=result[0],
|
||||
category=result[1],
|
||||
purchase_date=result[3],
|
||||
owner=user
|
||||
)
|
||||
|
||||
def generate_ticket_for_user(self, user_id: int, category: str) -> Optional[Ticket]:
|
||||
cursor = self._get_cursor()
|
||||
try:
|
||||
cursor.execute("INSERT INTO tickets (ticket_category, user) VALUES (?, ?)", (category, user_id))
|
||||
self._connection.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Error generating ticket for user: {e}")
|
||||
return
|
||||
|
||||
return self.get_ticket_for_user(user_id)
|
||||
|
||||
def change_ticket_owner(self, ticket_id: int, new_owner_id: int) -> bool:
|
||||
cursor = self._get_cursor()
|
||||
try:
|
||||
cursor.execute("UPDATE tickets SET user = ? WHERE ticket_id = ?;", (new_owner_id, ticket_id))
|
||||
affected_rows = cursor.rowcount
|
||||
self._connection.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Error transferring ticket to user: {e}")
|
||||
return False
|
||||
return bool(affected_rows)
|
||||
|
||||
def delete_ticket(self, ticket_id: int) -> bool:
|
||||
cursor = self._get_cursor()
|
||||
try:
|
||||
cursor.execute("DELETE FROM tickets WHERE ticket_id = ?;", (ticket_id, ))
|
||||
self._connection.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"Error deleting ticket: {e}")
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -1,7 +1,73 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from src.ez_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
|
||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||
from src.ez_lan_manager.types.ConfigurationTypes import LanInfo
|
||||
from src.ez_lan_manager.types.Ticket import Ticket
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
class TicketNotAvailableError(Exception):
|
||||
def __init__(self, category: str):
|
||||
self.category = category
|
||||
|
||||
class UserAlreadyHasTicketError(Exception):
|
||||
pass
|
||||
|
||||
class TicketingService:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
def __init__(self, lan_info: LanInfo, db_service: DatabaseService, accounting_service: AccountingService) -> None:
|
||||
self._lan_info = lan_info
|
||||
self._db_service = db_service
|
||||
self._accounting_service = accounting_service
|
||||
|
||||
def get_total_tickets(self) -> int:
|
||||
return sum([self._lan_info.ticket_info.get_available_tickets(c) for c in self._lan_info.ticket_info.categories])
|
||||
|
||||
def get_available_tickets(self) -> dict[str, int]:
|
||||
result = self._lan_info.ticket_info.total_available_tickets
|
||||
all_tickets = self._db_service.get_tickets()
|
||||
for ticket in all_tickets:
|
||||
result[ticket.category] -= 1
|
||||
|
||||
return result
|
||||
|
||||
def purchase_ticket(self, user_id: int, category: str) -> Ticket:
|
||||
if category not in self._lan_info.ticket_info.categories or self.get_available_tickets()[category] < 1:
|
||||
raise TicketNotAvailableError(category)
|
||||
|
||||
user_balance = self._accounting_service.get_balance(user_id)
|
||||
if self._lan_info.ticket_info.get_price(category) > user_balance:
|
||||
raise InsufficientFundsError
|
||||
|
||||
if self.get_user_ticket(user_id):
|
||||
raise UserAlreadyHasTicketError
|
||||
|
||||
if new_ticket := self._db_service.generate_ticket_for_user(user_id, category):
|
||||
self._accounting_service.remove_balance(
|
||||
user_id,
|
||||
self._lan_info.ticket_info.get_price(new_ticket.category),
|
||||
f"TICKET {new_ticket.ticket_id}"
|
||||
)
|
||||
logger.debug(f"User {user_id} purchased ticket {new_ticket.ticket_id}")
|
||||
return new_ticket
|
||||
|
||||
raise RuntimeError("An unknown error occurred while purchasing ticket")
|
||||
|
||||
def refund_ticket(self, user_id: int) -> bool:
|
||||
user_ticket = self.get_user_ticket(user_id)
|
||||
if not user_ticket:
|
||||
return False
|
||||
|
||||
if self._db_service.delete_ticket(user_ticket.ticket_id):
|
||||
self._accounting_service.add_balance(user_id, self._lan_info.ticket_info.get_price(user_ticket.category), f"TICKET REFUND {user_ticket.ticket_id}")
|
||||
logger.debug(f"User {user_id} refunded ticket {user_ticket.ticket_id}")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def transfer_ticket(self, ticket_id: int, user_id: int) -> bool:
|
||||
return self._db_service.change_ticket_owner(ticket_id, user_id)
|
||||
|
||||
def get_user_ticket(self, user_id: int) -> Optional[Ticket]:
|
||||
return self._db_service.get_ticket_for_user(user_id)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from copy import copy
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
@ -30,6 +31,10 @@ class TicketInfo:
|
||||
except KeyError:
|
||||
raise NoSuchCategoryError
|
||||
|
||||
@property
|
||||
def total_available_tickets(self):
|
||||
return copy(self._available_tickets)
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MailingServiceConfiguration:
|
||||
smtp_server: str
|
||||
|
||||
13
src/ez_lan_manager/types/Ticket.py
Normal file
13
src/ez_lan_manager/types/Ticket.py
Normal file
@ -0,0 +1,13 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from src.ez_lan_manager.types.User import User
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Ticket:
|
||||
ticket_id: int
|
||||
category: str
|
||||
purchase_date: datetime
|
||||
owner: Optional[User] = None
|
||||
Loading…
Reference in New Issue
Block a user