From 210e01bb965837c0424d21b4c396724baee28f4d Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Sat, 30 May 2026 20:28:26 +0200 Subject: [PATCH] Add option to storno tickets and seats --- src/elm/pages/UserAdminPage.py | 75 ++++++++++++++++++++++++++- src/elm/services/AccountingService.py | 13 ++--- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/elm/pages/UserAdminPage.py b/src/elm/pages/UserAdminPage.py index bd988eb..517756f 100644 --- a/src/elm/pages/UserAdminPage.py +++ b/src/elm/pages/UserAdminPage.py @@ -1,15 +1,18 @@ from __future__ import annotations import logging +from copy import copy from functools import partial from typing import Optional from decimal import Decimal +from beanie.odm.interfaces.find import FindInterface +from bson import ObjectId from rio import Component, Column, Row, Text, Spacer, page, Rectangle, TextInput, GuardEvent, Button, TextInputChangeEvent, NumberInput, IconButton from rio.event import on_populate -from elm.types import UserSession, User, Transaction -from elm.services import AccountingService, MailingService +from elm.types import UserSession, User, Transaction, Ticket, Seat +from elm.services import AccountingService, MailingService, ConfigurationService from elm.components import AccountInfoBox logger = logging.getLogger(__name__.split(".")[-1]) @@ -95,6 +98,36 @@ class UserAdminPage(Component): receiver=self.active_user.user_mail )) + async def cancel_ticket(self) -> None: + if self.active_user is None: + return + + ticket = await Ticket.find_one({"owner.$id": self.active_user.id}) + if ticket is None: + return + + ticket_price = Decimal(0) + for ticket_info in self.session[ConfigurationService].get_ticket_info(): + if ticket_info.category == ticket.category: + ticket_price = ticket_info.price + + await ticket.delete() + await self.session[AccountingService].add_balance(self.active_user.user_name, ticket_price, "TICKET STORNO", skip_mail=True) + await self.free_seat() + + async def free_seat(self) -> None: + if self.active_user is None: + return + + seat = await Seat.find_one({"user.$id": ObjectId(self.active_user.id)}) + if seat is None: + self.active_user = None + return + + seat.user = None + await seat.save() + self.active_user = None + def build(self) -> Component: right_panel_contents = [] if not self.active_user: @@ -153,6 +186,44 @@ class UserAdminPage(Component): stroke_width=0.1, stroke_color=self.session.theme.box_border_color ), + Rectangle( + content=Column( + Rectangle( + content=Rectangle( + content=Text(f"Sonstiges", 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( + Row( + Button( + content="Ticket stornieren", + shape="rectangle", + color="danger", + margin=1, + on_press=self.cancel_ticket + ), + Button( + content="Sitzplatz freigeben", + shape="rectangle", + color="danger", + margin=1, + on_press=self.free_seat + ) + ), + margin=1, + spacing=1 + ), + Spacer() + ), + fill=self.session.theme.box_color, + stroke_width=0.1, + stroke_color=self.session.theme.box_border_color + ), ]) diff --git a/src/elm/services/AccountingService.py b/src/elm/services/AccountingService.py index d8a96ef..72aab5a 100644 --- a/src/elm/services/AccountingService.py +++ b/src/elm/services/AccountingService.py @@ -130,7 +130,7 @@ class AccountingService: return True return False - async def add_balance(self, user_name: str, balance_to_add: Decimal, title: str) -> Decimal: + async def add_balance(self, user_name: str, balance_to_add: Decimal, title: str, skip_mail: bool = False) -> Decimal: user = await User.find_one(User.user_name == user_name) if not user: raise KeyError("User does not exist") @@ -142,11 +142,12 @@ class AccountingService: ).save() logger.debug(f"Added balance of {self.make_euro_string_from_decimal(balance_to_add)} to user '{user_name}'") new_balance = await self.get_balance(user_name) - await self._mailing_service.send_email( - "Dein Guthaben wurde aufgeladen", - self._mailing_service.generate_account_balance_added_mail_body(user, balance_to_add, new_balance), - user.user_mail - ) + if not skip_mail: + await self._mailing_service.send_email( + "Dein Guthaben wurde aufgeladen", + self._mailing_service.generate_account_balance_added_mail_body(user, balance_to_add, new_balance), + user.user_mail + ) return new_balance async def remove_balance(self, user_name: str, balance_to_remove: Decimal, title: str) -> Decimal: