diff --git a/requirements.txt b/requirements.txt index efe7f09..ab1758b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -64,3 +64,4 @@ watchfiles==1.2.0 wcwidth==0.7.0 websockets==16.0 yarl==1.24.2 +requests==2.34.2 diff --git a/src/elm/__init__.py b/src/elm/__init__.py index eb5ba36..f1b8407 100644 --- a/src/elm/__init__.py +++ b/src/elm/__init__.py @@ -8,7 +8,7 @@ from from_root import from_root from rio import App, Theme, Color, Font, Icon, Session from elm.components.RootComponent import RootComponent -from elm.services import ConfigurationService, DatabaseService, UserService, LocalData, LocalDataService, MailingService, AccountingService, PreloadService +from elm.services import ConfigurationService, DatabaseService, UserService, LocalData, LocalDataService, MailingService, AccountingService, PreloadService, ReceiptPrintingService from elm.types import UserSession logger = logging.getLogger("ELM") @@ -79,7 +79,7 @@ app = App( theme=theme, assets_dir=Path(__file__).parent / "assets", build=RootComponent, - default_attachments=[LocalData(), configuration_service, database_service, UserService(), LocalDataService(), mailing_service, AccountingService(configuration_service, mailing_service), PreloadService()], + default_attachments=[LocalData(), configuration_service, database_service, UserService(), LocalDataService(), mailing_service, AccountingService(configuration_service, mailing_service), PreloadService(), ReceiptPrintingService(configuration_service.get_receipt_printing_configuration(), configuration_service.DEV_MODE_ACTIVE)], on_app_start=on_app_start, on_session_start=on_session_start, icon=from_root("src/elm/assets/img/favicon.png"), diff --git a/src/elm/components/CateringCart.py b/src/elm/components/CateringCart.py index 5b866b0..bb2df61 100644 --- a/src/elm/components/CateringCart.py +++ b/src/elm/components/CateringCart.py @@ -4,7 +4,7 @@ from functools import partial from rio import Component, Rectangle, Column, Text, Spacer, List, Row, IconButton from elm.components import ElmButton -from elm.services import AccountingService +from elm.services import AccountingService, ReceiptPrintingService from elm.types import User, UserSession from elm.types.CateringTypes import CateringOrderedItem, CateringOrder @@ -79,6 +79,8 @@ class CateringCart(Component): self.order_button_loading = False self.status_text = "Bestellt!" self.status_is_error = False + + self.session.create_task(self.session[ReceiptPrintingService].print_order(user, new_order)) return None diff --git a/src/elm/services/ReceiptPrintingService.py b/src/elm/services/ReceiptPrintingService.py new file mode 100644 index 0000000..592decc --- /dev/null +++ b/src/elm/services/ReceiptPrintingService.py @@ -0,0 +1,60 @@ +import logging +from datetime import timezone +from zoneinfo import ZoneInfo + +import requests +from bson import ObjectId + +from elm.types import Seat +from elm.types.CateringTypes import CateringOrder +from elm.types.ConfigurationTypes import ReceiptPrintingConfiguration +from elm.types.User import User + +logger = logging.getLogger(__name__.split(".")[-1]) +logging.getLogger("urllib3").setLevel(logging.FATAL) # Disable logging for urllib3 + +class ReceiptPrintingService: + def __init__(self, config: ReceiptPrintingConfiguration, dev_mode_enabled: bool) -> None: + self._config = config + self._dev_mode_enabled = dev_mode_enabled + self._url = f"http://{self._config.host}:{self._config.port}/{self._config.order_print_endpoint}" + + async def print_order(self, user: User, order: CateringOrder) -> None: + seat = await Seat.find_one({"user.$id": ObjectId(user.id)}) + if seat is None: + seat_id = " - " + else: + seat_id = str(seat.seat_id) + + + menu_items_payload = [] + for item in order.items: + menu_items_payload.append({ + "menu_item_name": item.name, + "mods": [f"{'MIT' if mod.selected else 'OHNE'} {mod.label}" for mod in item.selected_modifiers], + "amount": 1 + }) + + payload = { + "order_id": str(order.id)[-5:], + "order_date": order.created_at.replace(tzinfo=timezone.utc).astimezone(ZoneInfo("Europe/Berlin")).strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z', + "customer_name": user.user_name, + "seat_id": seat_id, + "items": menu_items_payload + } + + logger.info(f"Sending print order to {self._url}: {payload}") + try: + response = requests.post( + self._url, + json=payload, + headers={"x-password": self._config.password}, + timeout=2.0 + ) + if response.status_code != 200: + logger.error(f"Received an error with code {response.status_code}: {response.text}") + except Exception as e: + if self._dev_mode_enabled: + logger.info("An error occurred trying to print a receipt: %s", e) + return + logger.error("An error occurred trying to print a receipt: %s", e) diff --git a/src/elm/services/__init__.py b/src/elm/services/__init__.py index 6642d38..bec1abc 100644 --- a/src/elm/services/__init__.py +++ b/src/elm/services/__init__.py @@ -5,3 +5,4 @@ from .LocalDataService import LocalData, LocalDataService from .MailingService import MailingService from .AccountingService import AccountingService from .PreloadService import PreloadService +from .ReceiptPrintingService import ReceiptPrintingService