aiomysql refactor
This commit is contained in:
parent
a9597b5c4f
commit
30b32a4c02
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
@ -1,4 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from asyncio import get_event_loop
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -27,13 +29,7 @@ if __name__ == "__main__":
|
|||||||
corner_radius_large=0,
|
corner_radius_large=0,
|
||||||
font=Font(from_root("src/ez_lan_manager/assets/fonts/joystix.otf"))
|
font=Font(from_root("src/ez_lan_manager/assets/fonts/joystix.otf"))
|
||||||
)
|
)
|
||||||
|
services = init_services()
|
||||||
try:
|
|
||||||
services = init_services()
|
|
||||||
except NoDatabaseConnectionError:
|
|
||||||
logger.fatal("Could not connect to database, exiting...")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
lan_info = services[2].get_lan_info()
|
lan_info = services[2].get_lan_info()
|
||||||
|
|
||||||
@ -41,6 +37,12 @@ if __name__ == "__main__":
|
|||||||
await session.set_title(lan_info.name)
|
await session.set_title(lan_info.name)
|
||||||
session.attach(SessionStorage())
|
session.attach(SessionStorage())
|
||||||
|
|
||||||
|
async def on_app_start(a: App) -> None:
|
||||||
|
init_result = await a.default_attachments[3].init_db_pool()
|
||||||
|
if not init_result:
|
||||||
|
logger.fatal("Could not connect to database, exiting...")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
app = App(
|
app = App(
|
||||||
name="EZ LAN Manager",
|
name="EZ LAN Manager",
|
||||||
pages=[
|
pages=[
|
||||||
@ -138,6 +140,7 @@ if __name__ == "__main__":
|
|||||||
assets_dir=Path(__file__).parent / "assets",
|
assets_dir=Path(__file__).parent / "assets",
|
||||||
default_attachments=services,
|
default_attachments=services,
|
||||||
on_session_start=on_session_start,
|
on_session_start=on_session_start,
|
||||||
|
on_app_start=on_app_start,
|
||||||
icon=from_root("src/ez_lan_manager/assets/img/favicon.png"),
|
icon=from_root("src/ez_lan_manager/assets/img/favicon.png"),
|
||||||
meta_tags={
|
meta_tags={
|
||||||
"robots": "INDEX,FOLLOW",
|
"robots": "INDEX,FOLLOW",
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Callable
|
|
||||||
|
|
||||||
import rio
|
import rio
|
||||||
from rio import Component, Row, Text, IconButton, TextStyle, Color
|
from rio import Component, Row, Text, TextStyle, Color
|
||||||
|
|
||||||
from src.ez_lan_manager import AccountingService
|
|
||||||
from src.ez_lan_manager.types.CateringOrder import CateringOrderStatus
|
from src.ez_lan_manager.types.CateringOrder import CateringOrderStatus
|
||||||
|
|
||||||
MAX_LEN = 24
|
MAX_LEN = 24
|
||||||
|
|||||||
@ -6,19 +6,13 @@ from src.ez_lan_manager.components.UserInfoAndLoginBox import UserInfoAndLoginBo
|
|||||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||||
|
|
||||||
class DesktopNavigation(Component):
|
class DesktopNavigation(Component):
|
||||||
def __post_init__(self) -> None:
|
|
||||||
self.session[SessionStorage].subscribe_to_logged_in_or_out_event(self.__class__.__name__, self.refresh_cb)
|
|
||||||
|
|
||||||
async def refresh_cb(self) -> None:
|
|
||||||
await self.force_refresh()
|
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
lan_info = self.session[ConfigurationService].get_lan_info()
|
lan_info = self.session[ConfigurationService].get_lan_info()
|
||||||
return Card(
|
return Card(
|
||||||
Column(
|
Column(
|
||||||
Text(lan_info.name, align_x=0.5, margin_top=0.3, style=TextStyle(fill=self.session.theme.hud_color, font_size=2.5)),
|
Text(lan_info.name, align_x=0.5, margin_top=0.3, style=TextStyle(fill=self.session.theme.hud_color, font_size=2.5)),
|
||||||
Text(f"Edition {lan_info.iteration}", align_x=0.5, style=TextStyle(fill=self.session.theme.hud_color, font_size=1.2), margin_top=0.3, margin_bottom=2),
|
Text(f"Edition {lan_info.iteration}", align_x=0.5, style=TextStyle(fill=self.session.theme.hud_color, font_size=1.2), margin_top=0.3, margin_bottom=2),
|
||||||
UserInfoAndLoginBox(refresh_cb=self.refresh_cb),
|
UserInfoAndLoginBox(),
|
||||||
DesktopNavigationButton("News", "./news"),
|
DesktopNavigationButton("News", "./news"),
|
||||||
Spacer(min_height=1),
|
Spacer(min_height=1),
|
||||||
DesktopNavigationButton(f"Über {lan_info.name} {lan_info.iteration}", "./overview"),
|
DesktopNavigationButton(f"Über {lan_info.name} {lan_info.iteration}", "./overview"),
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
import rio
|
import rio
|
||||||
from rio import Component, Column, Text, TextStyle, Button, Row, ScrollContainer, Spacer
|
from rio import Component, Column, Text, TextStyle, Button, Row, ScrollContainer, Spacer
|
||||||
|
|
||||||
@ -11,9 +13,11 @@ from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
|||||||
|
|
||||||
class ShoppingCartAndOrders(Component):
|
class ShoppingCartAndOrders(Component):
|
||||||
show_cart: bool = True
|
show_cart: bool = True
|
||||||
|
orders: list[CateringOrder] = []
|
||||||
|
|
||||||
async def switch(self) -> None:
|
async def switch(self) -> None:
|
||||||
self.show_cart = not self.show_cart
|
self.show_cart = not self.show_cart
|
||||||
|
self.orders = await self.session[CateringService].get_orders_for_user(self.session[SessionStorage].user_id)
|
||||||
|
|
||||||
async def on_remove_item(self, list_id: int) -> None:
|
async def on_remove_item(self, list_id: int) -> None:
|
||||||
catering_service = self.session[CateringService]
|
catering_service = self.session[CateringService]
|
||||||
@ -36,7 +40,7 @@ class ShoppingCartAndOrders(Component):
|
|||||||
if not user_id:
|
if not user_id:
|
||||||
return
|
return
|
||||||
cart = catering_service.get_cart(user_id)
|
cart = catering_service.get_cart(user_id)
|
||||||
cart.append(catering_service.get_menu_item_by_id(article_id))
|
cart.append(await catering_service.get_menu_item_by_id(article_id))
|
||||||
catering_service.save_cart(user_id, cart)
|
catering_service.save_cart(user_id, cart)
|
||||||
await self.force_refresh()
|
await self.force_refresh()
|
||||||
|
|
||||||
@ -99,14 +103,13 @@ class ShoppingCartAndOrders(Component):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
orders = catering_service.get_orders_for_user(user_id)
|
|
||||||
orders_container = ScrollContainer(
|
orders_container = ScrollContainer(
|
||||||
content=Column(
|
content=Column(
|
||||||
*[CateringOrderItem(
|
*[CateringOrderItem(
|
||||||
order_id=order_item.order_id,
|
order_id=order_item.order_id,
|
||||||
order_datetime=order_item.order_date,
|
order_datetime=order_item.order_date,
|
||||||
order_status=order_item.status,
|
order_status=order_item.status,
|
||||||
) for order_item in orders],
|
) for order_item in self.orders],
|
||||||
Spacer(grow_y=True)
|
Spacer(grow_y=True)
|
||||||
),
|
),
|
||||||
min_height=8,
|
min_height=8,
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
import logging
|
import logging
|
||||||
from random import choice
|
from random import choice
|
||||||
from typing import Callable
|
from typing import Optional
|
||||||
|
|
||||||
from rio import Component, Column, Text, Row, Rectangle, Button, TextStyle, Color, Spacer, TextInput, Link
|
from rio import Component, Column, Text, Row, Rectangle, Button, TextStyle, Color, Spacer, TextInput, Link, event
|
||||||
|
|
||||||
from src.ez_lan_manager import UserService
|
from src.ez_lan_manager import UserService
|
||||||
from src.ez_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
|
from src.ez_lan_manager.components.UserInfoBoxButton import UserInfoBoxButton
|
||||||
from src.ez_lan_manager.services.AccountingService import AccountingService
|
from src.ez_lan_manager.services.AccountingService import AccountingService
|
||||||
from src.ez_lan_manager.services.DatabaseService import NoDatabaseConnectionError, DatabaseService
|
|
||||||
from src.ez_lan_manager.services.TicketingService import TicketingService
|
from src.ez_lan_manager.services.TicketingService import TicketingService
|
||||||
from src.ez_lan_manager.services.SeatingService import SeatingService
|
from src.ez_lan_manager.services.SeatingService import SeatingService
|
||||||
|
from src.ez_lan_manager.types.Seat import Seat
|
||||||
|
from src.ez_lan_manager.types.Ticket import Ticket
|
||||||
|
from src.ez_lan_manager.types.User import User
|
||||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||||
|
|
||||||
logger = logging.getLogger(__name__.split(".")[-1])
|
logger = logging.getLogger(__name__.split(".")[-1])
|
||||||
@ -39,9 +41,20 @@ class StatusButton(Component):
|
|||||||
|
|
||||||
|
|
||||||
class UserInfoAndLoginBox(Component):
|
class UserInfoAndLoginBox(Component):
|
||||||
refresh_cb: Callable
|
|
||||||
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
|
TEXT_STYLE = TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
|
||||||
show_login: bool = True
|
show_login: bool = True
|
||||||
|
user: Optional[User] = None
|
||||||
|
user_balance: Optional[int] = 0
|
||||||
|
user_ticket: Optional[Ticket] = None
|
||||||
|
user_seat: Optional[Seat] = None
|
||||||
|
|
||||||
|
@event.on_populate
|
||||||
|
async def async_init(self) -> None:
|
||||||
|
if self.session[SessionStorage].user_id:
|
||||||
|
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||||
|
self.user_balance = await self.session[AccountingService].get_balance(self.user.user_id)
|
||||||
|
self.user_ticket = await self.session[TicketingService].get_user_ticket(self.user.user_id)
|
||||||
|
self.user_seat = await self.session[SeatingService].get_user_seat(self.user.user_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_greeting() -> str:
|
def get_greeting() -> str:
|
||||||
@ -64,13 +77,13 @@ class UserInfoAndLoginBox(Component):
|
|||||||
|
|
||||||
async def _on_login_pressed(self) -> None:
|
async def _on_login_pressed(self) -> None:
|
||||||
user_name = self.user_name_input.text.lower()
|
user_name = self.user_name_input.text.lower()
|
||||||
if self.session[UserService].is_login_valid(user_name, self.password_input.text):
|
if await self.session[UserService].is_login_valid(user_name, self.password_input.text):
|
||||||
self.user_name_input.is_valid = True
|
self.user_name_input.is_valid = True
|
||||||
self.password_input.is_valid = True
|
self.password_input.is_valid = True
|
||||||
self.login_button.is_loading = False
|
self.login_button.is_loading = False
|
||||||
await self.session[SessionStorage].set_user_id(self.session[UserService].get_user(user_name).user_id)
|
await self.session[SessionStorage].set_user_id((await self.session[UserService].get_user(user_name)).user_id)
|
||||||
|
await self.async_init()
|
||||||
self.show_login = False
|
self.show_login = False
|
||||||
await self.refresh_cb()
|
|
||||||
else:
|
else:
|
||||||
self.user_name_input.is_valid = False
|
self.user_name_input.is_valid = False
|
||||||
self.password_input.is_valid = False
|
self.password_input.is_valid = False
|
||||||
@ -114,7 +127,7 @@ class UserInfoAndLoginBox(Component):
|
|||||||
on_press=lambda: self.session.navigate_to("./forgot-password")
|
on_press=lambda: self.session.navigate_to("./forgot-password")
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.show_login and self.session[SessionStorage].user_id is None:
|
if self.user is None and self.session[SessionStorage].user_id is None:
|
||||||
return Rectangle(
|
return Rectangle(
|
||||||
content=Column(
|
content=Column(
|
||||||
self.user_name_input,
|
self.user_name_input,
|
||||||
@ -139,25 +152,31 @@ class UserInfoAndLoginBox(Component):
|
|||||||
margin_top=0.3,
|
margin_top=0.3,
|
||||||
margin_bottom=2
|
margin_bottom=2
|
||||||
)
|
)
|
||||||
|
elif self.user is None and self.session[SessionStorage].user_id is not None:
|
||||||
|
return Rectangle(
|
||||||
|
content=Column(),
|
||||||
|
fill=Color.TRANSPARENT,
|
||||||
|
min_height=8,
|
||||||
|
min_width=12,
|
||||||
|
align_x=0.5,
|
||||||
|
margin_top=0.3,
|
||||||
|
margin_bottom=2
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
user = self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
|
||||||
if user is None:
|
|
||||||
logger.warning("User could not be found, this should not have happend.")
|
|
||||||
a_s = self.session[AccountingService]
|
|
||||||
return Rectangle(
|
return Rectangle(
|
||||||
content=Column(
|
content=Column(
|
||||||
Text(f"{self.get_greeting()},", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9), justify="center"),
|
Text(f"{self.get_greeting()},", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9), justify="center"),
|
||||||
Text(f"{user.user_name}", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=1.2), justify="center"),
|
Text(f"{self.user.user_name}", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=1.2), justify="center"),
|
||||||
Row(
|
Row(
|
||||||
StatusButton(label="TICKET", target_url="./buy_ticket",
|
StatusButton(label="TICKET", target_url="./buy_ticket",
|
||||||
enabled=self.session[TicketingService].get_user_ticket(user.user_id) is not None),
|
enabled=self.user_ticket is not None),
|
||||||
StatusButton(label="SITZPLATZ", target_url="./seating",
|
StatusButton(label="SITZPLATZ", target_url="./seating",
|
||||||
enabled=self.session[SeatingService].get_user_seat(user.user_id) is not None),
|
enabled=self.user_seat is not None),
|
||||||
proportions=(50, 50),
|
proportions=(50, 50),
|
||||||
grow_y=False
|
grow_y=False
|
||||||
),
|
),
|
||||||
UserInfoBoxButton("Profil bearbeiten", "./edit-profile"),
|
UserInfoBoxButton("Profil bearbeiten", "./edit-profile"),
|
||||||
UserInfoBoxButton(f"Guthaben: {a_s.make_euro_string_from_int(a_s.get_balance(user.user_id))}", "./account"),
|
UserInfoBoxButton(f"Guthaben: {self.session[AccountingService].make_euro_string_from_int(self.user_balance)}", "./account"),
|
||||||
Button(
|
Button(
|
||||||
content=Text("Ausloggen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.6)),
|
content=Text("Ausloggen", style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.6)),
|
||||||
shape="rectangle",
|
shape="rectangle",
|
||||||
|
|||||||
@ -1,22 +1,47 @@
|
|||||||
from rio import Column, Component, event, Text, TextStyle, Button, Color, Spacer, Revealer, Row
|
from asyncio import sleep
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from rio import Column, Component, event, Text, TextStyle, Button, Color, Spacer, Revealer, Row, ProgressCircle
|
||||||
|
|
||||||
from src.ez_lan_manager import ConfigurationService, UserService, AccountingService
|
from src.ez_lan_manager import ConfigurationService, UserService, AccountingService
|
||||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||||
from src.ez_lan_manager.pages import BasePage
|
from src.ez_lan_manager.pages import BasePage
|
||||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||||
|
from src.ez_lan_manager.types.Transaction import Transaction
|
||||||
|
from src.ez_lan_manager.types.User import User
|
||||||
|
|
||||||
|
|
||||||
class AccountPage(Component):
|
class AccountPage(Component):
|
||||||
|
user: Optional[User] = None
|
||||||
|
balance: Optional[int] = None
|
||||||
|
transaction_history: list[Transaction] = list()
|
||||||
|
|
||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Guthabenkonto")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Guthabenkonto")
|
||||||
|
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||||
|
self.balance = await self.session[AccountingService].get_balance(self.user.user_id)
|
||||||
|
self.transaction_history = await self.session[AccountingService].get_transaction_history(self.user.user_id)
|
||||||
|
|
||||||
async def _on_banking_info_press(self):
|
async def _on_banking_info_press(self):
|
||||||
self.banking_info_revealer.is_open = not self.banking_info_revealer.is_open
|
self.banking_info_revealer.is_open = not self.banking_info_revealer.is_open
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
user = self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
if not self.user and not self.balance:
|
||||||
a_s = self.session[AccountingService]
|
return BasePage(
|
||||||
|
content=Column(
|
||||||
|
MainViewContentBox(
|
||||||
|
ProgressCircle(
|
||||||
|
color="secondary",
|
||||||
|
align_x=0.5,
|
||||||
|
margin_top=2,
|
||||||
|
margin_bottom=2
|
||||||
|
)
|
||||||
|
),
|
||||||
|
align_y = 0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.banking_info_revealer = Revealer(
|
self.banking_info_revealer = Revealer(
|
||||||
header=None,
|
header=None,
|
||||||
content=Column(
|
content=Column(
|
||||||
@ -45,7 +70,7 @@ class AccountPage(Component):
|
|||||||
align_x=0.2
|
align_x=0.2
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
f"AUFLADUNG - {user.user_id} - {user.user_name}",
|
f"AUFLADUNG - {self.user.user_id} - {self.user.user_name}",
|
||||||
style=TextStyle(
|
style=TextStyle(
|
||||||
fill=self.session.theme.neutral_color
|
fill=self.session.theme.neutral_color
|
||||||
),
|
),
|
||||||
@ -73,7 +98,7 @@ class AccountPage(Component):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for transaction in sorted(self.session[AccountingService].get_transaction_history(user.user_id), key=lambda t: t.transaction_date, reverse=True):
|
for transaction in sorted(self.transaction_history, key=lambda t: t.transaction_date, reverse=True):
|
||||||
transaction_history.add(
|
transaction_history.add(
|
||||||
Row(
|
Row(
|
||||||
Text(
|
Text(
|
||||||
@ -89,7 +114,7 @@ class AccountPage(Component):
|
|||||||
align_x=0
|
align_x=0
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
f"{'-' if transaction.is_debit else '+'}{a_s.make_euro_string_from_int(transaction.value)}",
|
f"{'-' if transaction.is_debit else '+'}{AccountingService.make_euro_string_from_int(transaction.value)}",
|
||||||
style=TextStyle(
|
style=TextStyle(
|
||||||
fill=self.session.theme.danger_color if transaction.is_debit else self.session.theme.success_color,
|
fill=self.session.theme.danger_color if transaction.is_debit else self.session.theme.success_color,
|
||||||
font_size=0.8
|
font_size=0.8
|
||||||
@ -106,7 +131,7 @@ class AccountPage(Component):
|
|||||||
content=Column(
|
content=Column(
|
||||||
MainViewContentBox(
|
MainViewContentBox(
|
||||||
content=Text(
|
content=Text(
|
||||||
f"Kontostand: {a_s.make_euro_string_from_int(a_s.get_balance(user.user_id))}",
|
f"Kontostand: {AccountingService.make_euro_string_from_int(self.balance)}",
|
||||||
style=TextStyle(
|
style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
font_size=1.2
|
font_size=1.2
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from typing import * # type: ignore
|
|||||||
|
|
||||||
from rio import Component, event, Spacer, Card, Container, Column, Row, TextStyle, Color, Text
|
from rio import Component, event, Spacer, Card, Container, Column, Row, TextStyle, Color, Text
|
||||||
|
|
||||||
from src.ez_lan_manager import ConfigurationService, DatabaseService
|
from src.ez_lan_manager import ConfigurationService
|
||||||
from src.ez_lan_manager.components.DesktopNavigation import DesktopNavigation
|
from src.ez_lan_manager.components.DesktopNavigation import DesktopNavigation
|
||||||
|
|
||||||
class BasePage(Component):
|
class BasePage(Component):
|
||||||
@ -14,11 +14,6 @@ class BasePage(Component):
|
|||||||
async def on_window_size_change(self):
|
async def on_window_size_change(self):
|
||||||
await self.force_refresh()
|
await self.force_refresh()
|
||||||
|
|
||||||
@event.on_populate
|
|
||||||
async def check_db_connection(self):
|
|
||||||
if not self.session[DatabaseService].is_connected:
|
|
||||||
self.session.navigate_to("./db-error")
|
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
if self.content is None:
|
if self.content is None:
|
||||||
content = Spacer()
|
content = Spacer()
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
from rio import Column, Component, event, TextStyle, Text, Spacer, Revealer, SwitcherBar, SwitcherBarChangeEvent
|
from typing import Optional
|
||||||
|
|
||||||
|
from rio import Column, Component, event, TextStyle, Text, Spacer, Revealer, SwitcherBar, SwitcherBarChangeEvent, ProgressCircle
|
||||||
|
|
||||||
from src.ez_lan_manager import ConfigurationService, CateringService
|
from src.ez_lan_manager import ConfigurationService, CateringService
|
||||||
from src.ez_lan_manager.components.CateringSelectionItem import CateringSelectionItem
|
from src.ez_lan_manager.components.CateringSelectionItem import CateringSelectionItem
|
||||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||||
from src.ez_lan_manager.components.ShoppingCartAndOrders import ShoppingCartAndOrders
|
from src.ez_lan_manager.components.ShoppingCartAndOrders import ShoppingCartAndOrders
|
||||||
from src.ez_lan_manager.pages import BasePage
|
from src.ez_lan_manager.pages import BasePage
|
||||||
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItemCategory
|
from src.ez_lan_manager.types.CateringMenuItem import CateringMenuItemCategory, CateringMenuItem
|
||||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||||
|
|
||||||
|
|
||||||
class CateringPage(Component):
|
class CateringPage(Component):
|
||||||
show_cart = True
|
show_cart = True
|
||||||
|
all_menu_items: Optional[list[CateringMenuItem]] = None
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
self.session[SessionStorage].subscribe_to_logged_in_or_out_event(self.__class__.__name__, self.on_user_logged_in_status_changed)
|
self.session[SessionStorage].subscribe_to_logged_in_or_out_event(self.__class__.__name__, self.on_user_logged_in_status_changed)
|
||||||
@ -18,6 +21,8 @@ class CateringPage(Component):
|
|||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Catering")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Catering")
|
||||||
|
self.all_menu_items = await self.session[CateringService].get_menu()
|
||||||
|
|
||||||
|
|
||||||
async def on_user_logged_in_status_changed(self) -> None:
|
async def on_user_logged_in_status_changed(self) -> None:
|
||||||
await self.force_refresh()
|
await self.force_refresh()
|
||||||
@ -25,9 +30,13 @@ class CateringPage(Component):
|
|||||||
async def on_switcher_bar_changed(self, _: SwitcherBarChangeEvent) -> None:
|
async def on_switcher_bar_changed(self, _: SwitcherBarChangeEvent) -> None:
|
||||||
await self.shopping_cart_and_orders.switch()
|
await self.shopping_cart_and_orders.switch()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_menu_items_by_category(all_menu_items: list[CateringMenuItem], category: Optional[CateringMenuItemCategory]) -> list[CateringMenuItem]:
|
||||||
|
return list(filter(lambda item: item.category == category, all_menu_items))
|
||||||
|
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
user_id = self.session[SessionStorage].user_id
|
user_id = self.session[SessionStorage].user_id
|
||||||
catering_service = self.session[CateringService]
|
|
||||||
self.shopping_cart_and_orders = ShoppingCartAndOrders()
|
self.shopping_cart_and_orders = ShoppingCartAndOrders()
|
||||||
switcher_bar = SwitcherBar(
|
switcher_bar = SwitcherBar(
|
||||||
values=["cart", "orders"],
|
values=["cart", "orders"],
|
||||||
@ -58,12 +67,14 @@ class CateringPage(Component):
|
|||||||
)
|
)
|
||||||
) if user_id else Spacer()
|
) if user_id else Spacer()
|
||||||
|
|
||||||
return BasePage(
|
menu = [MainViewContentBox(
|
||||||
content=Column(
|
ProgressCircle(
|
||||||
# SHOPPING CART
|
color="secondary",
|
||||||
shopping_cart_and_orders_container,
|
align_x=0.5,
|
||||||
# ITEM SELECTION
|
margin_top=2,
|
||||||
MainViewContentBox(
|
margin_bottom=2
|
||||||
|
)
|
||||||
|
)] if not self.all_menu_items else [MainViewContentBox(
|
||||||
Revealer(
|
Revealer(
|
||||||
header="Snacks",
|
header="Snacks",
|
||||||
content=Column(
|
content=Column(
|
||||||
@ -75,7 +86,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.SNACK))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.SNACK))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -97,7 +108,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.BREAKFAST))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.BREAKFAST))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -119,7 +130,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.MAIN_COURSE))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.MAIN_COURSE))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -141,7 +152,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.DESSERT))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.DESSERT))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -163,7 +174,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.BEVERAGE_NON_ALCOHOLIC))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -185,7 +196,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.BEVERAGE_ALCOHOLIC))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.BEVERAGE_ALCOHOLIC))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -207,7 +218,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.BEVERAGE_COCKTAIL))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.BEVERAGE_COCKTAIL))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -229,7 +240,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.BEVERAGE_SHOT))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.BEVERAGE_SHOT))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -251,7 +262,7 @@ class CateringPage(Component):
|
|||||||
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
is_sensitive=(user_id is not None) and not catering_menu_item.is_disabled,
|
||||||
additional_info=catering_menu_item.additional_info,
|
additional_info=catering_menu_item.additional_info,
|
||||||
is_grey=idx % 2 == 0
|
is_grey=idx % 2 == 0
|
||||||
) for idx, catering_menu_item in enumerate(catering_service.get_menu(CateringMenuItemCategory.NON_FOOD))],
|
) for idx, catering_menu_item in enumerate(self.get_menu_items_by_category(self.all_menu_items, CateringMenuItemCategory.NON_FOOD))],
|
||||||
),
|
),
|
||||||
header_style=TextStyle(
|
header_style=TextStyle(
|
||||||
fill=self.session.theme.background_color,
|
fill=self.session.theme.background_color,
|
||||||
@ -260,7 +271,14 @@ class CateringPage(Component):
|
|||||||
margin=1,
|
margin=1,
|
||||||
align_y=0.5
|
align_y=0.5
|
||||||
)
|
)
|
||||||
),
|
)]
|
||||||
|
|
||||||
|
return BasePage(
|
||||||
|
content=Column(
|
||||||
|
# SHOPPING CART
|
||||||
|
shopping_cart_and_orders_container,
|
||||||
|
# ITEM SELECTION
|
||||||
|
*menu,
|
||||||
align_y=0
|
align_y=0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from rio import Text, Column, TextStyle, Component, event, TextInput, MultiLineTextInput, Row, Button
|
from rio import Text, Column, TextStyle, Component, event, TextInput, MultiLineTextInput, Row, Button
|
||||||
|
|
||||||
@ -7,6 +8,7 @@ from src.ez_lan_manager.components.AnimatedText import AnimatedText
|
|||||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||||
from src.ez_lan_manager.pages import BasePage
|
from src.ez_lan_manager.pages import BasePage
|
||||||
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
from src.ez_lan_manager.types.SessionStorage import SessionStorage
|
||||||
|
from src.ez_lan_manager.types.User import User
|
||||||
|
|
||||||
|
|
||||||
class ContactPage(Component):
|
class ContactPage(Component):
|
||||||
@ -14,10 +16,15 @@ class ContactPage(Component):
|
|||||||
# Using list to bypass this behavior
|
# Using list to bypass this behavior
|
||||||
last_message_sent: list[datetime] = [datetime(day=1, month=1, year=2000)]
|
last_message_sent: list[datetime] = [datetime(day=1, month=1, year=2000)]
|
||||||
display_printing: list[bool] = [False]
|
display_printing: list[bool] = [False]
|
||||||
|
user: Optional[User] = None
|
||||||
|
|
||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Kontakt")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Kontakt")
|
||||||
|
if self.session[SessionStorage].user_id is not None:
|
||||||
|
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||||
|
else:
|
||||||
|
self.user = None
|
||||||
|
|
||||||
async def on_send_pressed(self) -> None:
|
async def on_send_pressed(self) -> None:
|
||||||
error_msg = ""
|
error_msg = ""
|
||||||
@ -51,11 +58,6 @@ class ContactPage(Component):
|
|||||||
await self.animated_text.display_text(True, "Nachricht erfolgreich gesendet!")
|
await self.animated_text.display_text(True, "Nachricht erfolgreich gesendet!")
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
if self.session[SessionStorage].user_id is not None:
|
|
||||||
user = self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
|
||||||
else:
|
|
||||||
user = None
|
|
||||||
|
|
||||||
self.animated_text = AnimatedText(
|
self.animated_text = AnimatedText(
|
||||||
margin_top = 2,
|
margin_top = 2,
|
||||||
margin_bottom = 1,
|
margin_bottom = 1,
|
||||||
@ -64,7 +66,7 @@ class ContactPage(Component):
|
|||||||
|
|
||||||
self.email_input = TextInput(
|
self.email_input = TextInput(
|
||||||
label="E-Mail Adresse",
|
label="E-Mail Adresse",
|
||||||
text="" if not user else user.user_mail,
|
text="" if not self.user else self.user.user_mail,
|
||||||
margin_left=1,
|
margin_left=1,
|
||||||
margin_right=1,
|
margin_right=1,
|
||||||
margin_bottom=1,
|
margin_bottom=1,
|
||||||
|
|||||||
@ -15,12 +15,12 @@ class DbErrorPage(Component):
|
|||||||
async def on_window_size_change(self) -> None:
|
async def on_window_size_change(self) -> None:
|
||||||
await self.force_refresh()
|
await self.force_refresh()
|
||||||
|
|
||||||
@event.on_mount
|
# @event.on_mount
|
||||||
async def retry_db_connect(self) -> None:
|
# async def retry_db_connect(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Fehler")
|
# await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Fehler")
|
||||||
while not self.session[DatabaseService].is_connected:
|
# while not self.session[DatabaseService].is_connected:
|
||||||
await sleep(2)
|
# await sleep(2)
|
||||||
self.session.navigate_to("./")
|
# self.session.navigate_to("./")
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
content = Card(
|
content = Card(
|
||||||
|
|||||||
@ -3,7 +3,8 @@ from hashlib import sha256
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from from_root import from_root
|
from from_root import from_root
|
||||||
from rio import Column, Component, event, Text, TextStyle, Button, Color, Row, TextInput, Image, TextInputChangeEvent, NoFileSelectedError
|
from rio import Column, Component, event, Text, TextStyle, Button, Color, Row, TextInput, Image, TextInputChangeEvent, NoFileSelectedError, \
|
||||||
|
ProgressCircle
|
||||||
from email_validator import validate_email, EmailNotValidError
|
from email_validator import validate_email, EmailNotValidError
|
||||||
|
|
||||||
from src.ez_lan_manager import ConfigurationService, UserService
|
from src.ez_lan_manager import ConfigurationService, UserService
|
||||||
@ -15,6 +16,8 @@ from src.ez_lan_manager.types.User import User
|
|||||||
|
|
||||||
|
|
||||||
class EditProfilePage(Component):
|
class EditProfilePage(Component):
|
||||||
|
user: Optional[User] = None
|
||||||
|
pfp: Optional[bytes] = None
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def optional_date_to_str(d: Optional[date]) -> str:
|
def optional_date_to_str(d: Optional[date]) -> str:
|
||||||
if not d:
|
if not d:
|
||||||
@ -24,6 +27,8 @@ class EditProfilePage(Component):
|
|||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Profil bearbeiten")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Profil bearbeiten")
|
||||||
|
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||||
|
self.pfp = await self.session[UserService].get_profile_picture(self.user.user_id)
|
||||||
|
|
||||||
def on_email_changed(self, change_event: TextInputChangeEvent) -> None:
|
def on_email_changed(self, change_event: TextInputChangeEvent) -> None:
|
||||||
try:
|
try:
|
||||||
@ -58,7 +63,7 @@ class EditProfilePage(Component):
|
|||||||
return
|
return
|
||||||
|
|
||||||
image_data = await new_pfp.read_bytes()
|
image_data = await new_pfp.read_bytes()
|
||||||
self.session[UserService].set_profile_picture(self.session[SessionStorage].user_id, image_data)
|
await self.session[UserService].set_profile_picture(self.session[SessionStorage].user_id, image_data)
|
||||||
self.pfp_image_container.image = image_data
|
self.pfp_image_container.image = image_data
|
||||||
await self.animated_text.display_text(True, "Gespeichert!")
|
await self.animated_text.display_text(True, "Gespeichert!")
|
||||||
|
|
||||||
@ -72,7 +77,7 @@ class EditProfilePage(Component):
|
|||||||
await self.animated_text.display_text(False, "Passwörter nicht gleich!")
|
await self.animated_text.display_text(False, "Passwörter nicht gleich!")
|
||||||
return
|
return
|
||||||
|
|
||||||
user: User = self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
user: User = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
||||||
user.user_mail = self.email_input.text
|
user.user_mail = self.email_input.text
|
||||||
|
|
||||||
if len(self.birthday_input.text) == 0:
|
if len(self.birthday_input.text) == 0:
|
||||||
@ -86,12 +91,24 @@ class EditProfilePage(Component):
|
|||||||
if len(self.new_pw_1_input.text.strip()) > 0:
|
if len(self.new_pw_1_input.text.strip()) > 0:
|
||||||
user.user_password = sha256(self.new_pw_1_input.text.encode(encoding="utf-8")).hexdigest()
|
user.user_password = sha256(self.new_pw_1_input.text.encode(encoding="utf-8")).hexdigest()
|
||||||
|
|
||||||
self.session[UserService].update_user(user)
|
await self.session[UserService].update_user(user)
|
||||||
await self.animated_text.display_text(True, "Gespeichert!")
|
await self.animated_text.display_text(True, "Gespeichert!")
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
user = self.session[UserService].get_user(self.session[SessionStorage].user_id)
|
if not self.user:
|
||||||
pfp = self.session[UserService].get_profile_picture(user.user_id)
|
return BasePage(
|
||||||
|
content=Column(
|
||||||
|
MainViewContentBox(
|
||||||
|
ProgressCircle(
|
||||||
|
color="secondary",
|
||||||
|
align_x=0.5,
|
||||||
|
margin_top=2,
|
||||||
|
margin_bottom=2
|
||||||
|
)
|
||||||
|
),
|
||||||
|
align_y = 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.animated_text = AnimatedText(
|
self.animated_text = AnimatedText(
|
||||||
margin_top=2,
|
margin_top=2,
|
||||||
@ -101,7 +118,7 @@ class EditProfilePage(Component):
|
|||||||
|
|
||||||
self.email_input = TextInput(
|
self.email_input = TextInput(
|
||||||
label="E-Mail Adresse",
|
label="E-Mail Adresse",
|
||||||
text=user.user_mail,
|
text=self.user.user_mail,
|
||||||
margin_left=1,
|
margin_left=1,
|
||||||
margin_right=1,
|
margin_right=1,
|
||||||
margin_bottom=1,
|
margin_bottom=1,
|
||||||
@ -110,20 +127,20 @@ class EditProfilePage(Component):
|
|||||||
)
|
)
|
||||||
self.first_name_input = TextInput(
|
self.first_name_input = TextInput(
|
||||||
label="Vorname",
|
label="Vorname",
|
||||||
text=user.user_first_name,
|
text=self.user.user_first_name,
|
||||||
margin_left=1,
|
margin_left=1,
|
||||||
margin_right=1,
|
margin_right=1,
|
||||||
grow_x=True
|
grow_x=True
|
||||||
)
|
)
|
||||||
self.last_name_input = TextInput(
|
self.last_name_input = TextInput(
|
||||||
label="Nachname",
|
label="Nachname",
|
||||||
text=user.user_last_name,
|
text=self.user.user_last_name,
|
||||||
margin_right=1,
|
margin_right=1,
|
||||||
grow_x=True
|
grow_x=True
|
||||||
)
|
)
|
||||||
self.birthday_input = TextInput(
|
self.birthday_input = TextInput(
|
||||||
label="Geburtstag (TT.MM.JJJJ)",
|
label="Geburtstag (TT.MM.JJJJ)",
|
||||||
text=self.optional_date_to_str(user.user_birth_day),
|
text=self.optional_date_to_str(self.user.user_birth_day),
|
||||||
margin_left=1,
|
margin_left=1,
|
||||||
margin_right=1,
|
margin_right=1,
|
||||||
margin_bottom=1,
|
margin_bottom=1,
|
||||||
@ -150,7 +167,7 @@ class EditProfilePage(Component):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.pfp_image_container = Image(
|
self.pfp_image_container = Image(
|
||||||
from_root("src/ez_lan_manager/assets/img/anon_pfp.png") if pfp is None else pfp,
|
from_root("src/ez_lan_manager/assets/img/anon_pfp.png") if self.pfp is None else self.pfp,
|
||||||
align_x=0.5,
|
align_x=0.5,
|
||||||
min_width=10,
|
min_width=10,
|
||||||
min_height=10,
|
min_height=10,
|
||||||
@ -176,8 +193,8 @@ class EditProfilePage(Component):
|
|||||||
on_press=self.upload_new_pfp
|
on_press=self.upload_new_pfp
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
TextInput(label="Deine User-ID", text=user.user_id, is_sensitive=False, margin_left=1, grow_x=False),
|
TextInput(label="Deine User-ID", text=self.user.user_id, is_sensitive=False, margin_left=1, grow_x=False),
|
||||||
TextInput(label="Dein Nickname", text=user.user_name, is_sensitive=False, margin_left=1, margin_right=1, grow_x=True),
|
TextInput(label="Dein Nickname", text=self.user.user_name, is_sensitive=False, margin_left=1, margin_right=1, grow_x=True),
|
||||||
margin_bottom=1
|
margin_bottom=1
|
||||||
),
|
),
|
||||||
self.email_input,
|
self.email_input,
|
||||||
|
|||||||
@ -24,11 +24,11 @@ class ForgotPasswordPage(Component):
|
|||||||
lan_info = self.session[ConfigurationService].get_lan_info()
|
lan_info = self.session[ConfigurationService].get_lan_info()
|
||||||
user_service = self.session[UserService]
|
user_service = self.session[UserService]
|
||||||
mailing_service = self.session[MailingService]
|
mailing_service = self.session[MailingService]
|
||||||
user = user_service.get_user(self.email_input.text.strip())
|
user = await user_service.get_user(self.email_input.text.strip())
|
||||||
if user is not None:
|
if user is not None:
|
||||||
new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16))
|
new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16))
|
||||||
user.user_password = sha256(new_password.encode(encoding="utf-8")).hexdigest()
|
user.user_password = sha256(new_password.encode(encoding="utf-8")).hexdigest()
|
||||||
user_service.update_user(user)
|
await user_service.update_user(user)
|
||||||
await mailing_service.send_email(
|
await mailing_service.send_email(
|
||||||
subject=f"Dein neues Passwort für {lan_info.name}",
|
subject=f"Dein neues Passwort für {lan_info.name}",
|
||||||
body=f"Du hast für den EZ-LAN Manager der {lan_info.name} ein neues Passwort angefragt. "
|
body=f"Du hast für den EZ-LAN Manager der {lan_info.name} ein neues Passwort angefragt. "
|
||||||
|
|||||||
@ -5,37 +5,50 @@ from rio import Column, Component, event, TextStyle, Text, Button, Row, TextInpu
|
|||||||
from src.ez_lan_manager import ConfigurationService, UserService, TicketingService, SeatingService
|
from src.ez_lan_manager import ConfigurationService, UserService, TicketingService, SeatingService
|
||||||
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox
|
||||||
from src.ez_lan_manager.pages import BasePage
|
from src.ez_lan_manager.pages import BasePage
|
||||||
|
from src.ez_lan_manager.types.Seat import Seat
|
||||||
from src.ez_lan_manager.types.User import User
|
from src.ez_lan_manager.types.User import User
|
||||||
|
|
||||||
|
|
||||||
class GuestsPage(Component):
|
class GuestsPage(Component):
|
||||||
table_elements: list[Button] = []
|
table_elements: list[Button] = []
|
||||||
users_with_tickets: list[User] = []
|
users_with_tickets: list[User] = []
|
||||||
|
users_with_seats: dict[User, Seat] = {}
|
||||||
user_filter: Optional[str] = None
|
user_filter: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
|
||||||
user_service = self.session[UserService]
|
|
||||||
all_users = user_service.get_all_users()
|
|
||||||
ticketing_service = self.session[TicketingService]
|
|
||||||
self.users_with_tickets = list(filter(lambda user: ticketing_service.get_user_ticket(user.user_id) is not None, all_users))
|
|
||||||
|
|
||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Teilnehmer")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Teilnehmer")
|
||||||
|
user_service = self.session[UserService]
|
||||||
|
all_users = await user_service.get_all_users()
|
||||||
|
ticketing_service = self.session[TicketingService]
|
||||||
|
seating_service = self.session[SeatingService]
|
||||||
|
u_w_t = []
|
||||||
|
u_w_s = {}
|
||||||
|
for user in all_users:
|
||||||
|
ticket = await ticketing_service.get_user_ticket(user.user_id)
|
||||||
|
seat = await seating_service.get_user_seat(user.user_id)
|
||||||
|
if ticket is not None:
|
||||||
|
u_w_t.append(user)
|
||||||
|
if seat is not None:
|
||||||
|
u_w_s[user] = seat
|
||||||
|
|
||||||
|
self.users_with_tickets = u_w_t
|
||||||
|
self.users_with_seats = u_w_s
|
||||||
|
|
||||||
def on_searchbar_content_change(self, change_event: TextInputChangeEvent) -> None:
|
def on_searchbar_content_change(self, change_event: TextInputChangeEvent) -> None:
|
||||||
self.user_filter = change_event.text
|
self.user_filter = change_event.text
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
seating_service = self.session[SeatingService]
|
|
||||||
if self.user_filter:
|
if self.user_filter:
|
||||||
users = [user for user in self.users_with_tickets if self.user_filter.lower() in user.user_name or self.user_filter.lower() in str(user.user_id)]
|
users = [user for user in self.users_with_tickets if self.user_filter.lower() in user.user_name or self.user_filter.lower() in str(user.user_id)]
|
||||||
else:
|
else:
|
||||||
users = self.users_with_tickets
|
users = self.users_with_tickets
|
||||||
self.table_elements.clear()
|
self.table_elements.clear()
|
||||||
for idx, user in enumerate(users):
|
for idx, user in enumerate(users):
|
||||||
seat = seating_service.get_user_seat(user.user_id)
|
try:
|
||||||
|
seat = self.users_with_seats[user]
|
||||||
|
except KeyError:
|
||||||
|
seat = None
|
||||||
self.table_elements.append(
|
self.table_elements.append(
|
||||||
Button(
|
Button(
|
||||||
content=Row(Text(text=f"{user.user_id:0>4}", align_x=0, margin_right=1), Text(text=user.user_name, grow_x=True, wrap="ellipsize"), Text(text="-" if seat is None else seat.seat_id, align_x=1)),
|
content=Row(Text(text=f"{user.user_id:0>4}", align_x=0, margin_right=1), Text(text=user.user_name, grow_x=True, wrap="ellipsize"), Text(text="-" if seat is None else seat.seat_id, align_x=1)),
|
||||||
|
|||||||
@ -12,7 +12,7 @@ class NewsPage(Component):
|
|||||||
@event.on_populate
|
@event.on_populate
|
||||||
async def on_populate(self) -> None:
|
async def on_populate(self) -> None:
|
||||||
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Neuigkeiten")
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Neuigkeiten")
|
||||||
self.news_posts = self.session[NewsService].get_news()[:8]
|
self.news_posts = (await self.session[NewsService].get_news())[:8]
|
||||||
|
|
||||||
def build(self) -> Component:
|
def build(self) -> Component:
|
||||||
posts = [NewsPost(
|
posts = [NewsPost(
|
||||||
|
|||||||
@ -62,13 +62,13 @@ class RegisterPage(Component):
|
|||||||
mailing_service = self.session[MailingService]
|
mailing_service = self.session[MailingService]
|
||||||
lan_info = self.session[ConfigurationService].get_lan_info()
|
lan_info = self.session[ConfigurationService].get_lan_info()
|
||||||
|
|
||||||
if user_service.get_user(self.email_input.text) is not None or user_service.get_user(self.user_name_input.text) is not None:
|
if await user_service.get_user(self.email_input.text) is not None or await user_service.get_user(self.user_name_input.text) is not None:
|
||||||
await self.animated_text.display_text(False, "Benutzername oder E-Mail bereits regestriert!")
|
await self.animated_text.display_text(False, "Benutzername oder E-Mail bereits regestriert!")
|
||||||
self.submit_button.is_loading = False
|
self.submit_button.is_loading = False
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
new_user = user_service.create_user(self.user_name_input.text, self.email_input.text, self.pw_1.text)
|
new_user = await user_service.create_user(self.user_name_input.text, self.email_input.text, self.pw_1.text)
|
||||||
if not new_user:
|
if not new_user:
|
||||||
raise RuntimeError("User could not be created")
|
raise RuntimeError("User could not be created")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -13,8 +13,8 @@ class AccountingService:
|
|||||||
def __init__(self, db_service: DatabaseService) -> None:
|
def __init__(self, db_service: DatabaseService) -> None:
|
||||||
self._db_service = db_service
|
self._db_service = db_service
|
||||||
|
|
||||||
def add_balance(self, user_id: int, balance_to_add: int, reference: str) -> int:
|
async def add_balance(self, user_id: int, balance_to_add: int, reference: str) -> int:
|
||||||
self._db_service.add_transaction(Transaction(
|
await self._db_service.add_transaction(Transaction(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
value=balance_to_add,
|
value=balance_to_add,
|
||||||
is_debit=False,
|
is_debit=False,
|
||||||
@ -22,13 +22,13 @@ class AccountingService:
|
|||||||
transaction_date=datetime.now()
|
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}")
|
logger.debug(f"Added balance of {self.make_euro_string_from_int(balance_to_add)} to user with ID {user_id}")
|
||||||
return self.get_balance(user_id)
|
return await self.get_balance(user_id)
|
||||||
|
|
||||||
def remove_balance(self, user_id: int, balance_to_remove: int, reference: str) -> int:
|
async def remove_balance(self, user_id: int, balance_to_remove: int, reference: str) -> int:
|
||||||
current_balance = self.get_balance(user_id)
|
current_balance = await self.get_balance(user_id)
|
||||||
if (current_balance - balance_to_remove) < 0:
|
if (current_balance - balance_to_remove) < 0:
|
||||||
raise InsufficientFundsError
|
raise InsufficientFundsError
|
||||||
self._db_service.add_transaction(Transaction(
|
await self._db_service.add_transaction(Transaction(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
value=balance_to_remove,
|
value=balance_to_remove,
|
||||||
is_debit=True,
|
is_debit=True,
|
||||||
@ -36,19 +36,19 @@ class AccountingService:
|
|||||||
transaction_date=datetime.now()
|
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}")
|
logger.debug(f"Removed balance of {self.make_euro_string_from_int(balance_to_remove)} to user with ID {user_id}")
|
||||||
return self.get_balance(user_id)
|
return await self.get_balance(user_id)
|
||||||
|
|
||||||
def get_balance(self, user_id: int) -> int:
|
async def get_balance(self, user_id: int) -> int:
|
||||||
balance_buffer = 0
|
balance_buffer = 0
|
||||||
for transaction in self._db_service.get_all_transactions_for_user(user_id):
|
for transaction in await self._db_service.get_all_transactions_for_user(user_id):
|
||||||
if transaction.is_debit:
|
if transaction.is_debit:
|
||||||
balance_buffer -= transaction.value
|
balance_buffer -= transaction.value
|
||||||
else:
|
else:
|
||||||
balance_buffer += transaction.value
|
balance_buffer += transaction.value
|
||||||
return balance_buffer
|
return balance_buffer
|
||||||
|
|
||||||
def get_transaction_history(self, user_id: int) -> list[Transaction]:
|
async def get_transaction_history(self, user_id: int) -> list[Transaction]:
|
||||||
return self._db_service.get_all_transactions_for_user(user_id)
|
return await self._db_service.get_all_transactions_for_user(user_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def make_euro_string_from_int(cent_int: int) -> str:
|
def make_euro_string_from_int(cent_int: int) -> str:
|
||||||
|
|||||||
@ -23,93 +23,93 @@ class CateringService:
|
|||||||
|
|
||||||
# ORDERS
|
# ORDERS
|
||||||
|
|
||||||
def place_order(self, menu_items: CateringMenuItemsWithAmount, user_id: int, is_delivery: bool = True) -> CateringOrder:
|
async def place_order(self, menu_items: CateringMenuItemsWithAmount, user_id: int, is_delivery: bool = True) -> CateringOrder:
|
||||||
for menu_item in menu_items:
|
for menu_item in menu_items:
|
||||||
if menu_item.is_disabled:
|
if menu_item.is_disabled:
|
||||||
raise CateringError("Order includes disabled items")
|
raise CateringError("Order includes disabled items")
|
||||||
|
|
||||||
user = self._user_service.get_user(user_id)
|
user = await self._user_service.get_user(user_id)
|
||||||
if not user:
|
if not user:
|
||||||
raise CateringError("User does not exist")
|
raise CateringError("User does not exist")
|
||||||
|
|
||||||
total_price = sum([item.price * quantity for item, quantity in menu_items.items()])
|
total_price = sum([item.price * quantity for item, quantity in menu_items.items()])
|
||||||
if self._accounting_service.get_balance(user_id) < total_price:
|
if await self._accounting_service.get_balance(user_id) < total_price:
|
||||||
raise CateringError("Insufficient funds")
|
raise CateringError("Insufficient funds")
|
||||||
|
|
||||||
order = self._db_service.add_new_order(menu_items, user_id, is_delivery)
|
order = await self._db_service.add_new_order(menu_items, user_id, is_delivery)
|
||||||
if order:
|
if order:
|
||||||
self._accounting_service.remove_balance(user_id, total_price, f"CATERING - {order.order_id}")
|
await self._accounting_service.remove_balance(user_id, total_price, f"CATERING - {order.order_id}")
|
||||||
logger.info(f"User '{order.customer.user_name}' (ID:{order.customer.user_id}) ordered from catering for {self._accounting_service.make_euro_string_from_int(total_price)}")
|
logger.info(f"User '{order.customer.user_name}' (ID:{order.customer.user_id}) ordered from catering for {self._accounting_service.make_euro_string_from_int(total_price)}")
|
||||||
return order
|
return order
|
||||||
|
|
||||||
def update_order_status(self, order_id: int, new_status: CateringOrderStatus) -> bool:
|
async def update_order_status(self, order_id: int, new_status: CateringOrderStatus) -> bool:
|
||||||
if new_status == CateringOrderStatus.CANCELED:
|
if new_status == CateringOrderStatus.CANCELED:
|
||||||
# Cancelled orders need to be refunded
|
# Cancelled orders need to be refunded
|
||||||
raise CateringError("Orders cannot be canceled this way, use CateringService.cancel_order")
|
raise CateringError("Orders cannot be canceled this way, use CateringService.cancel_order")
|
||||||
return self._db_service.change_order_status(order_id, new_status)
|
return await self._db_service.change_order_status(order_id, new_status)
|
||||||
|
|
||||||
def get_orders(self) -> list[CateringOrder]:
|
async def get_orders(self) -> list[CateringOrder]:
|
||||||
return self._db_service.get_orders()
|
return await self._db_service.get_orders()
|
||||||
|
|
||||||
def get_orders_for_user(self, user_id: int) -> list[CateringOrder]:
|
async def get_orders_for_user(self, user_id: int) -> list[CateringOrder]:
|
||||||
return self._db_service.get_orders(user_id=user_id)
|
return await self._db_service.get_orders(user_id=user_id)
|
||||||
|
|
||||||
def get_orders_by_status(self, status: CateringOrderStatus) -> list[CateringOrder]:
|
async def get_orders_by_status(self, status: CateringOrderStatus) -> list[CateringOrder]:
|
||||||
return self._db_service.get_orders(status=status)
|
return await self._db_service.get_orders(status=status)
|
||||||
|
|
||||||
def cancel_order(self, order: CateringOrder) -> bool:
|
async def cancel_order(self, order: CateringOrder) -> bool:
|
||||||
if self._db_service.change_order_status(order.order_id, CateringOrderStatus.CANCELED):
|
if self._db_service.change_order_status(order.order_id, CateringOrderStatus.CANCELED):
|
||||||
self._accounting_service.add_balance(order.customer.user_id, order.price, f"CATERING REFUND - {order.order_id}")
|
await self._accounting_service.add_balance(order.customer.user_id, order.price, f"CATERING REFUND - {order.order_id}")
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# MENU ITEMS
|
# MENU ITEMS
|
||||||
|
|
||||||
def get_menu(self, category: Optional[CateringMenuItemCategory] = None) -> list[CateringMenuItem]:
|
async def get_menu(self, category: Optional[CateringMenuItemCategory] = None) -> list[CateringMenuItem]:
|
||||||
items = self._db_service.get_menu_items()
|
items = await self._db_service.get_menu_items()
|
||||||
if not category:
|
if not category:
|
||||||
return items
|
return items
|
||||||
return list(filter(lambda item: item.category == category, items))
|
return list(filter(lambda item: item.category == category, items))
|
||||||
|
|
||||||
def get_menu_item_by_id(self, menu_item_id: int) -> CateringMenuItem:
|
async def get_menu_item_by_id(self, menu_item_id: int) -> CateringMenuItem:
|
||||||
item = self._db_service.get_menu_item(menu_item_id)
|
item = await self._db_service.get_menu_item(menu_item_id)
|
||||||
if not item:
|
if not item:
|
||||||
raise CateringError("Menu item not found")
|
raise CateringError("Menu item not found")
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def add_menu_item(self, name: str, info: str, price: int, category: CateringMenuItemCategory, is_disabled: bool = False) -> CateringMenuItem:
|
async def add_menu_item(self, name: str, info: str, price: int, category: CateringMenuItemCategory, is_disabled: bool = False) -> CateringMenuItem:
|
||||||
if new_item := self._db_service.add_menu_item(name, info, price, category, is_disabled):
|
if new_item := await self._db_service.add_menu_item(name, info, price, category, is_disabled):
|
||||||
return new_item
|
return new_item
|
||||||
raise CateringError(f"Could not add item '{name}' to the menu.")
|
raise CateringError(f"Could not add item '{name}' to the menu.")
|
||||||
|
|
||||||
def remove_menu_item(self, menu_item_id: int) -> bool:
|
async def remove_menu_item(self, menu_item_id: int) -> bool:
|
||||||
return self._db_service.delete_menu_item(menu_item_id)
|
return await self._db_service.delete_menu_item(menu_item_id)
|
||||||
|
|
||||||
def change_menu_item(self, updated_item: CateringMenuItem) -> bool:
|
async def change_menu_item(self, updated_item: CateringMenuItem) -> bool:
|
||||||
return self._db_service.update_menu_item(updated_item)
|
return await self._db_service.update_menu_item(updated_item)
|
||||||
|
|
||||||
def disable_menu_item(self, menu_item_id: int) -> bool:
|
async def disable_menu_item(self, menu_item_id: int) -> bool:
|
||||||
try:
|
try:
|
||||||
item = self.get_menu_item_by_id(menu_item_id)
|
item = await self.get_menu_item_by_id(menu_item_id)
|
||||||
except CateringError:
|
except CateringError:
|
||||||
return False
|
return False
|
||||||
item.is_disabled = True
|
item.is_disabled = True
|
||||||
return self._db_service.update_menu_item(item)
|
return await self._db_service.update_menu_item(item)
|
||||||
|
|
||||||
def enable_menu_item(self, menu_item_id: int) -> bool:
|
async def enable_menu_item(self, menu_item_id: int) -> bool:
|
||||||
try:
|
try:
|
||||||
item = self.get_menu_item_by_id(menu_item_id)
|
item = await self.get_menu_item_by_id(menu_item_id)
|
||||||
except CateringError:
|
except CateringError:
|
||||||
return False
|
return False
|
||||||
item.is_disabled = False
|
item.is_disabled = False
|
||||||
return self._db_service.update_menu_item(item)
|
return await self._db_service.update_menu_item(item)
|
||||||
|
|
||||||
def disable_menu_items_by_category(self, category: CateringMenuItemCategory) -> bool:
|
async def disable_menu_items_by_category(self, category: CateringMenuItemCategory) -> bool:
|
||||||
items = self.get_menu(category=category)
|
items = await self.get_menu(category=category)
|
||||||
return all([self.disable_menu_item(item.item_id) for item in items])
|
return all([self.disable_menu_item(item.item_id) for item in items])
|
||||||
|
|
||||||
def enable_menu_items_by_category(self, category: CateringMenuItemCategory) -> bool:
|
async def enable_menu_items_by_category(self, category: CateringMenuItemCategory) -> bool:
|
||||||
items = self.get_menu(category=category)
|
items = await self.get_menu(category=category)
|
||||||
return all([self.enable_menu_item(item.item_id) for item in items])
|
return all([self.enable_menu_item(item.item_id) for item in items])
|
||||||
|
|
||||||
# CART
|
# CART
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import date, datetime
|
from datetime import date
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
from src.ez_lan_manager.services.DatabaseService import DatabaseService
|
||||||
@ -11,21 +11,22 @@ class NewsService:
|
|||||||
def __init__(self, db_service: DatabaseService) -> None:
|
def __init__(self, db_service: DatabaseService) -> None:
|
||||||
self._db_service = db_service
|
self._db_service = db_service
|
||||||
|
|
||||||
def add_news(self, news: News) -> None:
|
async def add_news(self, news: News) -> None:
|
||||||
if news.news_id is not None:
|
if news.news_id is not None:
|
||||||
logger.warning("Can not add news with ID, ignoring...")
|
logger.warning("Can not add news with ID, ignoring...")
|
||||||
return
|
return
|
||||||
self._db_service.add_news(news)
|
await self._db_service.add_news(news)
|
||||||
|
|
||||||
def get_news(self, dt_start: Optional[date] = None, dt_end: Optional[date] = None) -> list[News]:
|
async def get_news(self, dt_start: Optional[date] = None, dt_end: Optional[date] = None) -> list[News]:
|
||||||
if not dt_end:
|
if not dt_end:
|
||||||
dt_end = date.today()
|
dt_end = date.today()
|
||||||
if not dt_start:
|
if not dt_start:
|
||||||
dt_start = date(1900, 1, 1)
|
dt_start = date(1900, 1, 1)
|
||||||
return self._db_service.get_news(dt_start, dt_end)
|
return await self._db_service.get_news(dt_start, dt_end)
|
||||||
|
|
||||||
def get_latest_news(self) -> Optional[News]:
|
async def get_latest_news(self) -> Optional[News]:
|
||||||
try:
|
try:
|
||||||
return self.get_news(None, date.today())[0]
|
all_news = await self.get_news(None, date.today())
|
||||||
|
return all_news[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
logger.debug("There are no news to fetch")
|
logger.debug("There are no news to fetch")
|
||||||
|
|||||||
@ -36,27 +36,27 @@ class SeatingService:
|
|||||||
ElementTree.parse(self._seating_configuration.base_svg_path).write(self._seating_plan, encoding="unicode")
|
ElementTree.parse(self._seating_configuration.base_svg_path).write(self._seating_plan, encoding="unicode")
|
||||||
|
|
||||||
|
|
||||||
def get_seating(self) -> list[Seat]:
|
async def get_seating(self) -> list[Seat]:
|
||||||
return self._db_service.get_seating_info()
|
return await self._db_service.get_seating_info()
|
||||||
|
|
||||||
def get_seat(self, seat_id: str, cached_data: Optional[list[Seat]] = None) -> Optional[Seat]:
|
async def get_seat(self, seat_id: str, cached_data: Optional[list[Seat]] = None) -> Optional[Seat]:
|
||||||
all_seats = self.get_seating() if not cached_data else cached_data
|
all_seats = await self.get_seating() if not cached_data else cached_data
|
||||||
for seat in all_seats:
|
for seat in all_seats:
|
||||||
if seat.seat_id == seat_id:
|
if seat.seat_id == seat_id:
|
||||||
return seat
|
return seat
|
||||||
|
|
||||||
def get_user_seat(self, user_id: int) -> Optional[Seat]:
|
async def get_user_seat(self, user_id: int) -> Optional[Seat]:
|
||||||
all_seats = self.get_seating()
|
all_seats = await self.get_seating()
|
||||||
for seat in all_seats:
|
for seat in all_seats:
|
||||||
if seat.user and seat.user.user_id == user_id:
|
if seat.user and seat.user.user_id == user_id:
|
||||||
return seat
|
return seat
|
||||||
|
|
||||||
def seat_user(self, user_id: int, seat_id: str) -> None:
|
async def seat_user(self, user_id: int, seat_id: str) -> None:
|
||||||
user_ticket = self._ticketing_service.get_user_ticket(user_id)
|
user_ticket = await self._ticketing_service.get_user_ticket(user_id)
|
||||||
if not user_ticket:
|
if not user_ticket:
|
||||||
raise NoTicketError
|
raise NoTicketError
|
||||||
|
|
||||||
seat = self.get_seat(seat_id)
|
seat = await self.get_seat(seat_id)
|
||||||
if not seat:
|
if not seat:
|
||||||
raise SeatNotFoundError
|
raise SeatNotFoundError
|
||||||
|
|
||||||
@ -66,10 +66,10 @@ class SeatingService:
|
|||||||
if seat.user is not None:
|
if seat.user is not None:
|
||||||
raise SeatAlreadyTakenError
|
raise SeatAlreadyTakenError
|
||||||
|
|
||||||
self._db_service.seat_user(seat_id, user_id)
|
await self._db_service.seat_user(seat_id, user_id)
|
||||||
self.update_svg_with_seating_status()
|
await self.update_svg_with_seating_status()
|
||||||
|
|
||||||
def generate_new_seating_table(self, seating_plan_fp: Path, no_confirm: bool = False) -> None:
|
async def generate_new_seating_table(self, seating_plan_fp: Path, no_confirm: bool = False) -> None:
|
||||||
if not no_confirm:
|
if not no_confirm:
|
||||||
confirm = input("WARNING: THIS ACTION WILL DELETE ALL SEATING DATA! TYPE 'AGREE' TO CONTINUE: ")
|
confirm = input("WARNING: THIS ACTION WILL DELETE ALL SEATING DATA! TYPE 'AGREE' TO CONTINUE: ")
|
||||||
if confirm != "AGREE":
|
if confirm != "AGREE":
|
||||||
@ -95,10 +95,10 @@ class SeatingService:
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._db_service.generate_fresh_seats_table(sorted(seat_ids, key=lambda sd: sd[0]))
|
await self._db_service.generate_fresh_seats_table(sorted(seat_ids, key=lambda sd: sd[0]))
|
||||||
self.update_svg_with_seating_status()
|
await self.update_svg_with_seating_status()
|
||||||
|
|
||||||
def update_svg_with_seating_status(self) -> None:
|
async def update_svg_with_seating_status(self) -> None:
|
||||||
et = ElementTree.parse(self._seating_configuration.base_svg_path)
|
et = ElementTree.parse(self._seating_configuration.base_svg_path)
|
||||||
root = et.getroot()
|
root = et.getroot()
|
||||||
namespace = {'svg': root.tag.split('}')[0].strip('{')} if '}' in root.tag else {}
|
namespace = {'svg': root.tag.split('}')[0].strip('{')} if '}' in root.tag else {}
|
||||||
@ -113,13 +113,13 @@ class SeatingService:
|
|||||||
rect_g_pairs.append((last_rect, elem))
|
rect_g_pairs.append((last_rect, elem))
|
||||||
last_rect = None
|
last_rect = None
|
||||||
|
|
||||||
all_seats = self.get_seating()
|
all_seats = await self.get_seating()
|
||||||
|
|
||||||
for rect, g in rect_g_pairs:
|
for rect, g in rect_g_pairs:
|
||||||
seat_id = self.get_seat_id_from_element(g, namespace)
|
seat_id = self.get_seat_id_from_element(g, namespace)
|
||||||
if not seat_id:
|
if not seat_id:
|
||||||
continue
|
continue
|
||||||
seat = self.get_seat(seat_id, cached_data=all_seats)
|
seat = await self.get_seat(seat_id, cached_data=all_seats)
|
||||||
if not seat.is_blocked and seat.user is None:
|
if not seat.is_blocked and seat.user is None:
|
||||||
rect.set("fill", "rgb(102, 255, 51)")
|
rect.set("fill", "rgb(102, 255, 51)")
|
||||||
elif not seat.is_blocked and seat.user is not None:
|
elif not seat.is_blocked and seat.user is not None:
|
||||||
|
|||||||
@ -21,30 +21,30 @@ class TicketingService:
|
|||||||
self._db_service = db_service
|
self._db_service = db_service
|
||||||
self._accounting_service = accounting_service
|
self._accounting_service = accounting_service
|
||||||
|
|
||||||
def get_total_tickets(self) -> int:
|
async 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])
|
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]:
|
async def get_available_tickets(self) -> dict[str, int]:
|
||||||
result = self._lan_info.ticket_info.total_available_tickets
|
result = self._lan_info.ticket_info.total_available_tickets
|
||||||
all_tickets = self._db_service.get_tickets()
|
all_tickets = await self._db_service.get_tickets()
|
||||||
for ticket in all_tickets:
|
for ticket in all_tickets:
|
||||||
result[ticket.category] -= 1
|
result[ticket.category] -= 1
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def purchase_ticket(self, user_id: int, category: str) -> Ticket:
|
async 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:
|
if category not in self._lan_info.ticket_info.categories or (await self.get_available_tickets())[category] < 1:
|
||||||
raise TicketNotAvailableError(category)
|
raise TicketNotAvailableError(category)
|
||||||
|
|
||||||
user_balance = self._accounting_service.get_balance(user_id)
|
user_balance = await self._accounting_service.get_balance(user_id)
|
||||||
if self._lan_info.ticket_info.get_price(category) > user_balance:
|
if self._lan_info.ticket_info.get_price(category) > user_balance:
|
||||||
raise InsufficientFundsError
|
raise InsufficientFundsError
|
||||||
|
|
||||||
if self.get_user_ticket(user_id):
|
if self.get_user_ticket(user_id):
|
||||||
raise UserAlreadyHasTicketError
|
raise UserAlreadyHasTicketError
|
||||||
|
|
||||||
if new_ticket := self._db_service.generate_ticket_for_user(user_id, category):
|
if new_ticket := await self._db_service.generate_ticket_for_user(user_id, category):
|
||||||
self._accounting_service.remove_balance(
|
await self._accounting_service.remove_balance(
|
||||||
user_id,
|
user_id,
|
||||||
self._lan_info.ticket_info.get_price(new_ticket.category),
|
self._lan_info.ticket_info.get_price(new_ticket.category),
|
||||||
f"TICKET {new_ticket.ticket_id}"
|
f"TICKET {new_ticket.ticket_id}"
|
||||||
@ -54,20 +54,20 @@ class TicketingService:
|
|||||||
|
|
||||||
raise RuntimeError("An unknown error occurred while purchasing ticket")
|
raise RuntimeError("An unknown error occurred while purchasing ticket")
|
||||||
|
|
||||||
def refund_ticket(self, user_id: int) -> bool:
|
async def refund_ticket(self, user_id: int) -> bool:
|
||||||
user_ticket = self.get_user_ticket(user_id)
|
user_ticket = await self.get_user_ticket(user_id)
|
||||||
if not user_ticket:
|
if not user_ticket:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self._db_service.delete_ticket(user_ticket.ticket_id):
|
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}")
|
await 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}")
|
logger.debug(f"User {user_id} refunded ticket {user_ticket.ticket_id}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def transfer_ticket(self, ticket_id: int, user_id: int) -> bool:
|
async def transfer_ticket(self, ticket_id: int, user_id: int) -> bool:
|
||||||
return self._db_service.change_ticket_owner(ticket_id, user_id)
|
return await self._db_service.change_ticket_owner(ticket_id, user_id)
|
||||||
|
|
||||||
def get_user_ticket(self, user_id: int) -> Optional[Ticket]:
|
async def get_user_ticket(self, user_id: int) -> Optional[Ticket]:
|
||||||
return self._db_service.get_ticket_for_user(user_id)
|
return await self._db_service.get_ticket_for_user(user_id)
|
||||||
|
|||||||
@ -17,26 +17,26 @@ class UserService:
|
|||||||
def __init__(self, db_service: DatabaseService) -> None:
|
def __init__(self, db_service: DatabaseService) -> None:
|
||||||
self._db_service = db_service
|
self._db_service = db_service
|
||||||
|
|
||||||
def get_all_users(self) -> list[User]:
|
async def get_all_users(self) -> list[User]:
|
||||||
return self._db_service.get_all_users()
|
return await self._db_service.get_all_users()
|
||||||
|
|
||||||
def get_user(self, accessor: Optional[Union[str, int]]) -> Optional[User]:
|
async def get_user(self, accessor: Optional[Union[str, int]]) -> Optional[User]:
|
||||||
if accessor is None:
|
if accessor is None:
|
||||||
return
|
return
|
||||||
if isinstance(accessor, int):
|
if isinstance(accessor, int):
|
||||||
return self._db_service.get_user_by_id(accessor)
|
return await self._db_service.get_user_by_id(accessor)
|
||||||
accessor = accessor.lower()
|
accessor = accessor.lower()
|
||||||
if "@" in accessor:
|
if "@" in accessor:
|
||||||
return self._db_service.get_user_by_mail(accessor)
|
return await self._db_service.get_user_by_mail(accessor)
|
||||||
return self._db_service.get_user_by_name(accessor)
|
return await self._db_service.get_user_by_name(accessor)
|
||||||
|
|
||||||
def set_profile_picture(self, user_id: int, picture: bytes) -> None:
|
async def set_profile_picture(self, user_id: int, picture: bytes) -> None:
|
||||||
self._db_service.set_user_profile_picture(user_id, picture)
|
await self._db_service.set_user_profile_picture(user_id, picture)
|
||||||
|
|
||||||
def get_profile_picture(self, user_id: int) -> bytes:
|
async def get_profile_picture(self, user_id: int) -> bytes:
|
||||||
return self._db_service.get_user_profile_picture(user_id)
|
return await self._db_service.get_user_profile_picture(user_id)
|
||||||
|
|
||||||
def create_user(self, user_name: str, user_mail: str, password_clear_text: str) -> User:
|
async def create_user(self, user_name: str, user_mail: str, password_clear_text: str) -> User:
|
||||||
disallowed_char = self._check_for_disallowed_char(user_name)
|
disallowed_char = self._check_for_disallowed_char(user_name)
|
||||||
if disallowed_char:
|
if disallowed_char:
|
||||||
raise NameNotAllowedError(disallowed_char)
|
raise NameNotAllowedError(disallowed_char)
|
||||||
@ -44,17 +44,17 @@ class UserService:
|
|||||||
user_name = user_name.lower()
|
user_name = user_name.lower()
|
||||||
|
|
||||||
hashed_pw = sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
|
hashed_pw = sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
|
||||||
return self._db_service.create_user(user_name, user_mail, hashed_pw)
|
return await self._db_service.create_user(user_name, user_mail, hashed_pw)
|
||||||
|
|
||||||
def update_user(self, user: User) -> User:
|
async def update_user(self, user: User) -> User:
|
||||||
disallowed_char = self._check_for_disallowed_char(user.user_name)
|
disallowed_char = self._check_for_disallowed_char(user.user_name)
|
||||||
if disallowed_char:
|
if disallowed_char:
|
||||||
raise NameNotAllowedError(disallowed_char)
|
raise NameNotAllowedError(disallowed_char)
|
||||||
user.user_name = user.user_name.lower()
|
user.user_name = user.user_name.lower()
|
||||||
return self._db_service.update_user(user)
|
return await self._db_service.update_user(user)
|
||||||
|
|
||||||
def is_login_valid(self, user_name_or_mail: str, password_clear_text: str) -> bool:
|
async def is_login_valid(self, user_name_or_mail: str, password_clear_text: str) -> bool:
|
||||||
user = self.get_user(user_name_or_mail)
|
user = await self.get_user(user_name_or_mail)
|
||||||
if not user:
|
if not user:
|
||||||
return False
|
return False
|
||||||
return user.user_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
|
return user.user_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
|
||||||
|
|||||||
@ -17,3 +17,6 @@ class User:
|
|||||||
is_admin: bool
|
is_admin: bool
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
last_updated_at: datetime
|
last_updated_at: datetime
|
||||||
|
|
||||||
|
def __hash__(self) -> int:
|
||||||
|
return hash(f"{self.user_id}{self.user_name}{self.user_mail}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user