225 lines
10 KiB
Python
225 lines
10 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from datetime import date, datetime
|
|
from decimal import Decimal, ROUND_DOWN
|
|
from typing import Optional
|
|
|
|
from rio import Component, Column, Row, Text, Spacer, page, Rectangle, TextInput, GuardEvent, DateInput, PointerEventListener, Revealer, Image, NumberInput
|
|
from rio.event import on_populate
|
|
|
|
from elm.types import UserSession, Transaction
|
|
from elm.services import UserService, AccountingService
|
|
from elm.components import ElmButton, AvatarEditBox, AccountInfoBox
|
|
|
|
logger = logging.getLogger(__name__.split(".")[-1])
|
|
|
|
class TransactionRow(Component):
|
|
transaction_time: datetime
|
|
transaction_title: str
|
|
transaction_amount: Decimal
|
|
is_debit: bool
|
|
|
|
def build(self) -> Component:
|
|
color = self.session.theme.danger_color if self.is_debit else self.session.theme.success_color
|
|
return Rectangle(
|
|
content=Row(
|
|
Text(
|
|
f"{self.transaction_time.strftime("%d.%m.%y")} /",
|
|
justify="left",
|
|
font_size=0.8,
|
|
margin_left=0.5,
|
|
fill=color
|
|
),
|
|
Text(
|
|
self.transaction_title,
|
|
justify="left",
|
|
font_size=0.8,
|
|
margin_left=0.5,
|
|
fill=color,
|
|
overflow="ellipsize",
|
|
grow_x=True
|
|
),
|
|
Text(
|
|
f"{'-' if self.is_debit else '+'}{str(self.transaction_amount.quantize(Decimal('.01'), rounding=ROUND_DOWN))} €",
|
|
justify="right",
|
|
font_size=0.8,
|
|
margin_right=0.5,
|
|
fill=color
|
|
),
|
|
margin_bottom=0.5,
|
|
margin_top=0.5
|
|
),
|
|
hover_fill=self.session.theme.background_color,
|
|
transition_time=0.2
|
|
)
|
|
|
|
def my_balance_page_guard(event: GuardEvent) -> Optional[str]:
|
|
try:
|
|
_ = event.session[UserSession].user_name
|
|
return None
|
|
except KeyError:
|
|
return "/"
|
|
|
|
@page(name="My Balance", url_segment="balance", guard=my_balance_page_guard)
|
|
class MyBalancePage(Component):
|
|
current_balance: str = "-"
|
|
last_20_transactions: list[Transaction] = []
|
|
bank_revealer_open: bool = False
|
|
paypal_revealer_open: bool = False
|
|
payment_qr_image: bytes = bytes()
|
|
paypal_charge_amount: float = 0.00
|
|
paypal_charge_in_progress: bool = False
|
|
|
|
@on_populate
|
|
async def async_init(self) -> None:
|
|
self.current_balance = self.session[AccountingService].make_euro_string_from_decimal(
|
|
await self.session[AccountingService].get_balance(self.session[UserSession].user_name)
|
|
)
|
|
|
|
self.last_20_transactions = (await self.session[AccountingService].get_transaction_history(self.session[UserSession].user_name))[:20]
|
|
self.payment_qr_image = self.session[AccountingService].make_payment_qr_image(
|
|
"Einfach Zocken Gaming Gesellschaft",
|
|
"GENODE51BIK",
|
|
"DE47517624340019856607",
|
|
f"AUFLADUNG - {self.session[UserSession].user_name}")
|
|
|
|
async def pay_with_paypal(self) -> None:
|
|
self.paypal_charge_in_progress = True
|
|
logger.info("Starting PayPal transaction over %s for user %s", f"{self.paypal_charge_amount} €", self.session[UserSession].user_name)
|
|
amount = Decimal(self.paypal_charge_amount)
|
|
approval_url = await self.session[AccountingService].start_paypal_process(self.session[UserSession].user_name, amount)
|
|
self.session.open_url_in_browser(approval_url)
|
|
# ToDo: Catch return URL somehow and notify user
|
|
|
|
async def toggle_bank_revealer(self) -> None:
|
|
self.bank_revealer_open = not self.bank_revealer_open
|
|
|
|
async def toggle_paypal_revealer(self) -> None:
|
|
self.paypal_revealer_open = not self.paypal_revealer_open
|
|
|
|
def build(self) -> Component:
|
|
col_row = Column if self.session.is_mobile() else Row
|
|
|
|
transaction_rows = []
|
|
for transaction in sorted(self.last_20_transactions, key=lambda t: t.transaction_date, reverse=True):
|
|
transaction_rows.append(
|
|
TransactionRow(
|
|
transaction_time=transaction.transaction_date,
|
|
transaction_title=transaction.title,
|
|
transaction_amount=transaction.value,
|
|
is_debit=transaction.is_debit
|
|
)
|
|
)
|
|
|
|
return col_row(
|
|
Column(
|
|
Rectangle(
|
|
content=Column(
|
|
Rectangle(
|
|
content=Rectangle(
|
|
content=Text("Guthaben", 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(
|
|
Text(
|
|
text=self.current_balance,
|
|
justify="center",
|
|
font_size=2,
|
|
grow_x=True,
|
|
grow_y=True,
|
|
margin_top=2,
|
|
margin_bottom=1
|
|
),
|
|
Spacer(),
|
|
margin=1,
|
|
spacing=1
|
|
)
|
|
),
|
|
fill=self.session.theme.box_color,
|
|
stroke_width=0.1,
|
|
stroke_color=self.session.theme.box_border_color
|
|
),
|
|
Rectangle(
|
|
content=Column(
|
|
Rectangle(
|
|
content=Rectangle(
|
|
content=Text("Guthaben aufladen", 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(
|
|
ElmButton(text="Banküberweißung", style="small" if self.session.is_mobile() else "normal", on_press=self.toggle_bank_revealer),
|
|
Revealer(header=None, is_open=self.bank_revealer_open, content=Column(
|
|
Text("QR Code", justify="center"),
|
|
Image(self.payment_qr_image, min_width=14, min_height=14, margin_bottom=1),
|
|
Text("Bankverbindung", justify="center"),
|
|
Text("Empfänger: Einfach Zocken Gaming Gesellschaft", justify="left", overflow="wrap", font_size=0.7),
|
|
Text("IBAN: DE47517624340019856607", justify="left", overflow="wrap", font_size=0.7),
|
|
Text("BIC: GENODE51BIK", justify="left", overflow="wrap", font_size=0.7),
|
|
Text(f"Verwendungszweck: AUFLADUNG - {self.session[UserSession].user_name}", justify="left", overflow="wrap", font_size=0.7),
|
|
spacing=1
|
|
)),
|
|
ElmButton(text="Paypal", style="small" if self.session.is_mobile() else "normal", on_press=self.toggle_paypal_revealer),
|
|
Revealer(header=None, is_open=self.paypal_revealer_open, content=Column(
|
|
NumberInput(label="Summe", decimals=2, value=self.bind().paypal_charge_amount, suffix_text="€"),
|
|
ElmButton(text="Jetzt aufladen", style="small" if self.session.is_mobile() else "normal", on_press=self.pay_with_paypal, is_loading=self.paypal_charge_in_progress),
|
|
spacing=1
|
|
)),
|
|
margin=1,
|
|
spacing=1
|
|
)
|
|
),
|
|
fill=self.session.theme.box_color,
|
|
stroke_width=0.1,
|
|
stroke_color=self.session.theme.box_border_color
|
|
),
|
|
Spacer(),
|
|
spacing=1
|
|
),
|
|
Column(
|
|
Rectangle(
|
|
content=Column(
|
|
Rectangle(
|
|
content=Rectangle(
|
|
content=Text("Letzte Transaktionen", 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(
|
|
Rectangle(
|
|
content=Row(
|
|
Text("Datum / Titel", justify="left", font_size=0.8, margin_left=0.5),
|
|
Text("Betrag", justify="right", font_size=0.8, margin_right=0.5),
|
|
margin_bottom=0.5,
|
|
margin_top=0.5
|
|
)
|
|
),
|
|
*transaction_rows,
|
|
spacing=0.5,
|
|
margin=1
|
|
)
|
|
),
|
|
fill=self.session.theme.box_color,
|
|
stroke_width=0.1,
|
|
stroke_color=self.session.theme.box_border_color
|
|
),
|
|
Spacer(),
|
|
spacing=1,
|
|
grow_x=True
|
|
),
|
|
spacing=1,
|
|
margin=1,
|
|
margin_right=2
|
|
)
|