187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
import logging
|
|
from dataclasses import field, dataclass
|
|
from datetime import datetime
|
|
from typing import Optional, Callable
|
|
|
|
from rio import Column, Component, event, TextStyle, Text, Spacer, PointerEvent, Button, Popup, Card, Row
|
|
|
|
from src.ezgg_lan_manager import ConfigurationService, CateringService, SeatingService, AccountingService
|
|
from src.ezgg_lan_manager.components.CateringManagementOrderDisplay import CateringManagementOrderDisplay
|
|
from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox
|
|
from src.ezgg_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus
|
|
from src.ezgg_lan_manager.types.Seat import Seat
|
|
|
|
logger = logging.getLogger(__name__.split(".")[-1])
|
|
|
|
|
|
class CateringOrderInfoPopup(Component):
|
|
order: Optional[CateringOrder] = None
|
|
close_cb: Optional[Callable] = None
|
|
|
|
def build(self) -> Component:
|
|
if not self.order:
|
|
return Card(
|
|
content=Text(""),
|
|
margin=1,
|
|
color=self.session.theme.hud_color,
|
|
min_width=40,
|
|
min_height=40,
|
|
on_press=self.close_cb
|
|
)
|
|
rows = []
|
|
is_contrast_line = True
|
|
for item, amount in self.order.items.items():
|
|
style = TextStyle(
|
|
fill=self.session.theme.secondary_color if is_contrast_line else self.session.theme.neutral_color)
|
|
is_contrast_line = not is_contrast_line
|
|
rows.append(
|
|
Row(
|
|
Text(f"{amount}x", style=style),
|
|
Spacer(),
|
|
Text(f"{item.name}", style=style)
|
|
)
|
|
)
|
|
return Card(
|
|
content=Column(
|
|
Text(f"Bestellung {self.order.order_id}", style=TextStyle(font_size=1.2), margin_bottom=1),
|
|
*rows,
|
|
Spacer(),
|
|
Row(Text("Gesamtpreis:"), Spacer(),
|
|
Text(self.session[AccountingService].make_euro_string_from_decimal(self.order.price)))
|
|
),
|
|
margin=1,
|
|
color=self.session.theme.hud_color,
|
|
min_width=40,
|
|
min_height=40,
|
|
on_press=self.close_cb,
|
|
corner_radius=0.5,
|
|
elevate_on_hover=False,
|
|
colorize_on_hover=False
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class CateringOrderWithSeat:
|
|
catering_order: CateringOrder
|
|
seat: Optional[Seat]
|
|
|
|
|
|
class ManageCateringPage(Component):
|
|
all_orders: list[CateringOrderWithSeat] = field(default_factory=list)
|
|
last_updated: Optional[datetime] = None
|
|
order_popup_open: bool = False
|
|
order_popup_order: Optional[CateringOrder] = None
|
|
|
|
@event.on_populate
|
|
async def on_populate(self) -> None:
|
|
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Catering Verwaltung")
|
|
self.all_orders = await self.populate_seating(await self.session[CateringService].get_orders())
|
|
self.last_updated = datetime.now()
|
|
|
|
@event.periodic(30)
|
|
async def update_orders(self) -> None:
|
|
polled_orders = await self.session[CateringService].get_orders()
|
|
self.all_orders = await self.populate_seating(polled_orders)
|
|
self.last_updated = datetime.now()
|
|
|
|
async def populate_seating(self, orders: list[CateringOrder]) -> list[CateringOrderWithSeat]:
|
|
result = []
|
|
for order in orders:
|
|
seat = await self.session[SeatingService].get_user_seat(order.customer.user_id)
|
|
result.append(CateringOrderWithSeat(catering_order=order, seat=seat))
|
|
return result
|
|
|
|
def get_all_pending_orders(self) -> list[CateringOrderWithSeat]:
|
|
filtered_list = list(filter(lambda
|
|
o: o.catering_order.status != CateringOrderStatus.COMPLETED and o.catering_order.status != CateringOrderStatus.CANCELED,
|
|
self.all_orders))
|
|
sorted_list = sorted(filtered_list, key=lambda o: o.catering_order.order_date)
|
|
return sorted_list
|
|
|
|
def get_all_completed_orders(self) -> list[CateringOrderWithSeat]:
|
|
filtered_list = list(filter(lambda
|
|
o: o.catering_order.status == CateringOrderStatus.COMPLETED or o.catering_order.status == CateringOrderStatus.CANCELED,
|
|
self.all_orders))
|
|
sorted_list = sorted(filtered_list, key=lambda o: o.catering_order.order_date)
|
|
return sorted_list
|
|
|
|
async def order_clicked(self, order: CateringOrder, _: PointerEvent) -> None:
|
|
self.order_popup_order = order
|
|
self.order_popup_open = True
|
|
|
|
async def close_cb(self) -> None:
|
|
self.order_popup_open = False
|
|
|
|
def build(self) -> Component:
|
|
header_text = Text(
|
|
text="Catering Verwaltung",
|
|
style=TextStyle(
|
|
fill=self.session.theme.background_color,
|
|
font_size=1.2
|
|
),
|
|
margin_top=2,
|
|
margin_bottom=2,
|
|
align_x=0.5
|
|
)
|
|
popup = Popup(
|
|
anchor=header_text,
|
|
content=CateringOrderInfoPopup(order=self.order_popup_order, close_cb=self.close_cb),
|
|
is_open=self.order_popup_open,
|
|
position="bottom",
|
|
corner_radius=0.5
|
|
)
|
|
return Column(
|
|
MainViewContentBox(
|
|
Column(popup)
|
|
),
|
|
MainViewContentBox(
|
|
Column(
|
|
Text(
|
|
text="Offene Bestellungen",
|
|
style=TextStyle(
|
|
fill=self.session.theme.background_color,
|
|
font_size=1.2
|
|
),
|
|
margin_top=2,
|
|
margin_bottom=0.2,
|
|
align_x=0.5
|
|
),
|
|
Text(
|
|
text=f"Letzte Aktualisierung: {'-' if not self.last_updated else self.last_updated.strftime('%H:%M:%S')}",
|
|
style=TextStyle(
|
|
fill=self.session.theme.background_color,
|
|
font_size=0.7
|
|
),
|
|
margin_top=0.2,
|
|
margin_bottom=0.2,
|
|
align_x=0.5
|
|
),
|
|
Button(
|
|
content=Text("Jetzt aktualisieren", style=TextStyle(font_size=0.7), justify="center"),
|
|
shape="rectangle",
|
|
margin_bottom=1,
|
|
on_press=self.update_orders
|
|
),
|
|
*[CateringManagementOrderDisplay(v.catering_order, v.seat, self.order_clicked) for v in
|
|
self.get_all_pending_orders()],
|
|
)
|
|
),
|
|
MainViewContentBox(
|
|
Column(
|
|
Text(
|
|
text="Abgeschlossene Bestellungen",
|
|
style=TextStyle(
|
|
fill=self.session.theme.background_color,
|
|
font_size=1.2
|
|
),
|
|
margin_top=2,
|
|
margin_bottom=0.2,
|
|
align_x=0.5
|
|
),
|
|
*[CateringManagementOrderDisplay(v.catering_order, v.seat, self.order_clicked) for v in
|
|
self.get_all_completed_orders()],
|
|
)
|
|
),
|
|
Spacer()
|
|
)
|