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.MailingService import MailingService
|
||||||
from src.ez_lan_manager.services.NewsService import NewsService
|
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.services.UserService import UserService
|
||||||
from src.ez_lan_manager.types.News import News
|
from src.ez_lan_manager.types.News import News
|
||||||
from src.ez_lan_manager.types.Transaction import Transaction
|
from src.ez_lan_manager.types.Transaction import Transaction
|
||||||
@ -21,13 +22,17 @@ logger = logging.getLogger(__name__.split(".")[-1])
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
configuration_service = ConfigurationService(from_root("config.toml"))
|
configuration_service = ConfigurationService(from_root("config.toml"))
|
||||||
|
lan_info = configuration_service.get_lan_info()
|
||||||
db_config = configuration_service.get_database_configuration()
|
db_config = configuration_service.get_database_configuration()
|
||||||
db_service = DatabaseService(db_config)
|
db_service = DatabaseService(db_config)
|
||||||
user_service = UserService(db_service)
|
user_service = UserService(db_service)
|
||||||
accounting_service = AccountingService(db_service)
|
accounting_service = AccountingService(db_service)
|
||||||
news_service = NewsService(db_service)
|
news_service = NewsService(db_service)
|
||||||
mailing_service = MailingService(configuration_service.get_mailing_service_configuration())
|
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")
|
#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.ConfigurationTypes import DatabaseConfiguration
|
||||||
from src.ez_lan_manager.types.News import News
|
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.Transaction import Transaction
|
||||||
from src.ez_lan_manager.types.User import User
|
from src.ez_lan_manager.types.User import User
|
||||||
|
|
||||||
@ -178,3 +179,75 @@ class DatabaseService:
|
|||||||
))
|
))
|
||||||
|
|
||||||
return results
|
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
|
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])
|
logger = logging.getLogger(__name__.split(".")[-1])
|
||||||
|
|
||||||
|
class TicketNotAvailableError(Exception):
|
||||||
|
def __init__(self, category: str):
|
||||||
|
self.category = category
|
||||||
|
|
||||||
|
class UserAlreadyHasTicketError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class TicketingService:
|
class TicketingService:
|
||||||
def __init__(self) -> None:
|
def __init__(self, lan_info: LanInfo, db_service: DatabaseService, accounting_service: AccountingService) -> None:
|
||||||
pass
|
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 dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@ -30,6 +31,10 @@ class TicketInfo:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise NoSuchCategoryError
|
raise NoSuchCategoryError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_available_tickets(self):
|
||||||
|
return copy(self._available_tickets)
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class MailingServiceConfiguration:
|
class MailingServiceConfiguration:
|
||||||
smtp_server: str
|
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