prerelease/0.6.0 (#1)
Co-authored-by: David Rodenkirchen <drodenkirchen@linetco.com> Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from asyncio import sleep
|
||||
from functools import partial
|
||||
from typing import Optional
|
||||
from decimal import Decimal
|
||||
|
||||
from beanie import PydanticObjectId
|
||||
from rio import Component, Column, Row, Text, Spacer, page, Rectangle, GuardEvent, FlowContainer, List, PointerEventListener, Overlay, Link, Switch, SwitchChangeEvent
|
||||
from rio.event import on_populate
|
||||
|
||||
from elm.types import UserSession, User, Seat
|
||||
from elm.services import AccountingService, ReceiptPrintingService
|
||||
from elm.components import ElmButton
|
||||
from elm.types.CateringTypes import CateringOrder, CateringOrderStatus, CateringMenuItem, CateringMenuItemCategory
|
||||
|
||||
logger = logging.getLogger(__name__.split(".")[-1])
|
||||
|
||||
def catering_admin_page_guard(event: GuardEvent) -> Optional[str]:
|
||||
try:
|
||||
if event.session[UserSession].is_team_member:
|
||||
return None
|
||||
return "/"
|
||||
except KeyError:
|
||||
return "/"
|
||||
|
||||
@page(name="Cateringverwaltung", url_segment="catering-admin", guard=catering_admin_page_guard)
|
||||
class CateringAdminPage(Component):
|
||||
open_orders: List[CateringOrder] = List()
|
||||
all_users: list[User] = []
|
||||
all_seats: list[Seat] = []
|
||||
all_menu_items: list[CateringMenuItem] = []
|
||||
edited_order: Optional[CateringOrder] = None
|
||||
|
||||
@on_populate
|
||||
async def on_populate(self) -> None:
|
||||
self.all_users = await User.find_all().to_list()
|
||||
self.all_seats = await Seat.find_all(fetch_links=True).to_list()
|
||||
self.all_menu_items = await CateringMenuItem.find_all(fetch_links=True).to_list()
|
||||
self.open_orders = List(await CateringOrder.find_many(
|
||||
{
|
||||
"status": {
|
||||
"$nin": [
|
||||
CateringOrderStatus.COMPLETED,
|
||||
CateringOrderStatus.CANCELED,
|
||||
]
|
||||
}
|
||||
}
|
||||
).to_list())
|
||||
await sleep(5)
|
||||
self.session.create_task(self.on_populate())
|
||||
|
||||
def get_name_for_user_id(self, id_: PydanticObjectId) -> str:
|
||||
return next(filter(lambda user: user.id == id_ ,self.all_users)).user_name
|
||||
|
||||
def get_seat_for_user_id(self, id_: PydanticObjectId) -> str:
|
||||
try:
|
||||
found_seat: Optional[Seat] = next(filter(lambda seat: seat.user is not None and seat.user.id == id_, self.all_seats), None)
|
||||
if found_seat:
|
||||
return found_seat.seat_id
|
||||
return "-"
|
||||
except Exception:
|
||||
return "-"
|
||||
|
||||
async def on_order_pressed(self, order: CateringOrder) -> None:
|
||||
self.edited_order = order
|
||||
|
||||
async def change_order_status(self, new_status: CateringOrderStatus) -> None:
|
||||
if not self.edited_order:
|
||||
return
|
||||
|
||||
if new_status == CateringOrderStatus.CANCELED:
|
||||
pass
|
||||
|
||||
if self.edited_order.status == new_status:
|
||||
self.edited_order = None
|
||||
return
|
||||
|
||||
if new_status == CateringOrderStatus.CANCELED:
|
||||
user = await User.find_one(User.id == self.edited_order.customer_id)
|
||||
if not user:
|
||||
self.edited_order = None
|
||||
return
|
||||
|
||||
price = Decimal(0)
|
||||
for item in self.edited_order.items:
|
||||
price += item.final_unit_price
|
||||
await self.session[AccountingService].add_balance(user.user_name, price, f"CATERING REFUND - {str(self.edited_order.id)[-5:]}")
|
||||
|
||||
self.edited_order.status = new_status
|
||||
await self.edited_order.save()
|
||||
self.open_orders = List(await CateringOrder.find_many(
|
||||
{
|
||||
"status": {
|
||||
"$nin": [
|
||||
CateringOrderStatus.COMPLETED,
|
||||
CateringOrderStatus.CANCELED,
|
||||
]
|
||||
}
|
||||
}
|
||||
).to_list())
|
||||
self.edited_order = None
|
||||
|
||||
async def print_receipt(self) -> None:
|
||||
if not self.edited_order:
|
||||
return
|
||||
user = await User.find_one(User.id == self.edited_order.customer_id)
|
||||
if not user:
|
||||
self.edited_order = None
|
||||
return
|
||||
self.session.create_task(self.session[ReceiptPrintingService].print_order(user, self.edited_order))
|
||||
self.edited_order = None
|
||||
|
||||
@staticmethod
|
||||
async def change_item_active(event: SwitchChangeEvent, item: CateringMenuItem) -> None:
|
||||
item.active = event.is_on
|
||||
await item.save()
|
||||
|
||||
def build(self) -> Component:
|
||||
if self.edited_order:
|
||||
overlay = [
|
||||
Overlay(
|
||||
content=Rectangle(
|
||||
content=Column(
|
||||
Text(f"Status ändern - Bestellung {str(self.edited_order.id)[-5:]}", margin_bottom=1),
|
||||
*[ElmButton(text=CateringOrder.translate_order_status(status), on_press=partial(self.change_order_status, status)) for status in CateringOrderStatus],
|
||||
Row(ElmButton(text="Bon drucken", on_press=self.print_receipt), ElmButton(text="Abbrechen", on_press=lambda: self.__setattr__("edited_order", None)), spacing=1, margin_top=2),
|
||||
spacing=0.5,
|
||||
margin=1
|
||||
),
|
||||
fill=self.session.theme.box_color,
|
||||
stroke_width=0.2,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
align_x=0.5,
|
||||
align_y=0.5
|
||||
)
|
||||
)
|
||||
]
|
||||
else:
|
||||
overlay = []
|
||||
return Row(
|
||||
*overlay,
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Rectangle(
|
||||
content=Rectangle(
|
||||
content=Row(
|
||||
Text("Offene Bestellungen", margin=0.5, selectable=False, overflow="wrap"),
|
||||
Link(content="Neue Bestellung", target_url="./new-pos-order")
|
||||
),
|
||||
fill=self.session.theme.header_box_background_color,
|
||||
margin=0.4
|
||||
),
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
FlowContainer(
|
||||
*[PointerEventListener(
|
||||
content=Rectangle(
|
||||
content=Column(
|
||||
Row(Text(f"ID:", font_size=1.2), Text(str(order.id)[-5:], justify="right", font_size=1.2)),
|
||||
Row(Text("Nutzer:", font_size=1.2), Text(self.get_name_for_user_id(order.customer_id), font_size=1.2, justify="right")),
|
||||
Row(Text(f"Sitzplatz:", font_size=1.2), Text(self.get_seat_for_user_id(order.customer_id), font_size=1.2, justify="right")),
|
||||
Row(Text(f"Status:", font_size=1.2), Text(CateringOrder.translate_order_status(order.status), font_size=1.2, justify="right"), margin_bottom=2),
|
||||
*[Text(item.name, overflow="ellipsize") for item in order.items],
|
||||
margin=0.5,
|
||||
spacing=0.2
|
||||
),
|
||||
stroke_color=self.session.theme.primary_color,
|
||||
stroke_width=0.1,
|
||||
cursor="pointer",
|
||||
hover_stroke_color=self.session.theme.warning_color,
|
||||
hover_stroke_width=0.1,
|
||||
min_width=30
|
||||
),
|
||||
on_press=lambda event, order=order: self.on_order_pressed(order),
|
||||
) for order in self.open_orders],
|
||||
Spacer(),
|
||||
spacing=1,
|
||||
margin=1
|
||||
),
|
||||
Spacer()
|
||||
),
|
||||
fill=self.session.theme.box_color,
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
min_width=25,
|
||||
grow_x=True,
|
||||
margin_right=1
|
||||
),
|
||||
Rectangle(
|
||||
content=Column(
|
||||
Rectangle(
|
||||
content=Rectangle(
|
||||
content=Text("Speisekarte", margin=0.5, selectable=False, overflow="wrap"),
|
||||
fill=self.session.theme.header_box_background_color,
|
||||
margin=0.4
|
||||
),
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
),
|
||||
Column(
|
||||
*[Column(
|
||||
Text(text=category.value, margin_bottom=1, margin_top=0.5, fill=self.session.theme.primary_color),
|
||||
*[Rectangle(
|
||||
content=Row(Text(text=item.name, overflow="ellipsize", grow_x=True), Switch(is_on=item.active, on_change=lambda event, item=item: self.change_item_active(event, item)), margin=0.1),
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color
|
||||
) for item in filter(lambda i: i.category == category, self.all_menu_items)],
|
||||
spacing=0.5
|
||||
) for category in CateringMenuItemCategory],
|
||||
spacing=0.5,
|
||||
margin=1
|
||||
),
|
||||
Spacer()
|
||||
),
|
||||
fill=self.session.theme.box_color,
|
||||
stroke_width=0.1,
|
||||
stroke_color=self.session.theme.box_border_color,
|
||||
min_width=25
|
||||
),
|
||||
margin=1
|
||||
)
|
||||
Reference in New Issue
Block a user