Files
KPK/closed_accountselect.py
T
2026-06-23 15:20:56 +02:00

255 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.metrics import dp
from kivy.clock import Clock
from kivy.effects.scroll import ScrollEffect
from kivy.logger import Logger
from ui_utils import ucet_ui_type, UCET_COLORS
import math
import data
import numberpad
from accountselect_base import BaseAccountSelectScreen
from ui_utils import _popup_info
COLS = 7
BTN_W = dp(150)
BTN_H = dp(120)
SP = dp(10)
PAD = dp(10)
class ClosedAccountSelectScreen(BaseAccountSelectScreen):
def __init__(
self,
*,
controller,
operation: str,
get_ucty,
on_done,
on_cancel,
allow_manual: bool = True,
**kwargs,):
super().__init__(**kwargs)
self.controller = controller
self.operation = operation
self.get_ucty = get_ucty
self.on_done = on_done
self.on_cancel = on_cancel
self.allow_manual = allow_manual
self._all_ucty: list[data.UcetSelect] = []
root = BoxLayout(orientation="vertical", spacing=dp(10), padding=dp(10))
self.search_input = TextInput(
hint_text="HLEDAT",
multiline=False,
size_hint_y=None,
height=dp(52),
font_size=dp(20),
padding=(dp(12), dp(12), dp(12), dp(8)),
)
self.search_input.bind(text=self._on_search_text)
root.add_widget(self.search_input)
self.scroll = ScrollView(
size_hint=(1, 1),
do_scroll_x=True,
do_scroll_y=True,
bar_width=dp(14),
scroll_type=["bars", "content"],
effect_cls=ScrollEffect,)
self.grid = GridLayout(
cols=COLS,
spacing=SP,
padding=PAD,
size_hint=(None, None),)
self.grid.bind(minimum_height=self.grid.setter("height"))
self.grid.width = COLS * BTN_W + (COLS - 1) * SP + 2 * PAD
self.scroll.add_widget(self.grid)
root.add_widget(self.scroll)
bottom = BoxLayout(size_hint_y=None, height=dp(70), spacing=dp(10))
if self.allow_manual:
bottom.add_widget(Button(
text="ZADAT ÚČET",
on_press=self._manual, # <- musí existovat
))
bottom.add_widget(Button(
text="ZPĚT",
on_press=lambda *_: self.on_cancel(),
))
root.add_widget(bottom)
self.add_widget(root)
def _manual(self, *_):
import numberpad
from kivy.uix.popup import Popup
pad = numberpad.NumberPad(
mode="number",
max_len=10,
allow_fraction=False,
on_accept=self._manual_accept,
on_cancel=self._manual_cancel,
)
self._manual_popup = Popup(
title="Zadat číslo účtu",
content=pad,
size_hint=(None, None),
size=(dp(360), dp(420)),
auto_dismiss=False,
)
self._manual_popup.open()
def _manual_accept(self, value: str):
if getattr(self, "_manual_popup", None):
self._manual_popup.dismiss()
self._manual_popup = None
value = (value or "").strip()
if not value:
return
self._select(value)
def _manual_cancel(self):
if getattr(self, "_manual_popup", None):
self._manual_popup.dismiss()
self._manual_popup = None
def on_enter(self):
self.refresh()
def _select(self, ucislo: int):
Logger.info(f"ClosedSelect: picked ucislo={ucislo} op={self.operation}")
self.on_done(self.operation, ucislo)
def _update_scroll(self, *_):
if not self.scroll or not self.grid:
return
count = len(self.grid.children)
if count == 0:
self.scroll.do_scroll_x = False
self.scroll.do_scroll_y = False
return
rows = math.ceil(count / COLS)
content_h = rows * BTN_H + (rows - 1) * SP + 2 * PAD
self.scroll.do_scroll_y = content_h > self.scroll.height
def _create_ucet_button(self, u: data.UcetSelect):
ui_type = ucet_ui_type(u)
color = UCET_COLORS.get(ui_type, (0.3, 0.3, 0.3, 1))
txt = self._format_closed_ucet(u) or ""
if not txt.strip():
txt = f"ID {getattr(u, 'id', '')}"
btn = Button(
text=txt,
size_hint=(None, None),
background_color=color,
width=BTN_W,
height=dp(130), # lehce vyšší pro 45 řádků
font_size=dp(12), # trochu menší
halign="center",
valign="top", )
btn.bind(
size=lambda b, *_: setattr(
b, "text_size", (b.width - dp(10), None)
))
ucislo = getattr(u, "ucislo", None)
if ucislo is None:
btn.disabled = True
btn.opacity = 0.4
return btn
btn.ucislo = ucislo
btn.bind(on_press=lambda b: self._select(b.ucislo))
return btn
def _format_closed_ucet(self, u):
lines = []
# --- měna (fallback) potreba najit alesponmenu s s kurzem 1!!!
unit = (
getattr(u, "unit", None)
or getattr(u, "mena", None)
or getattr(u, "currency", None)
or "Kč"
)
# 1) origin + stůl
txt = ""
if getattr(u, "origin", None):
txt += f"{u.origin}"
if getattr(u, "stul", None):
if txt:
txt += " "
txt += f"stůl {u.stul}"
if txt:
lines.append(txt)
# 2) číslo účtu + čas uzavření
txt = ""
if getattr(u, "ucislo", None):
txt += f"{u.ucislo}"
if getattr(u, "autor", None):
if txt:
txt += f" | by {u.autor}"
if txt:
lines.append(txt)
txt = ""
if getattr(u, "closed_at", None): #zatim nech
if txt:
txt += " | "
txt += f"{u.closed_at}"
if txt:
lines.append(txt)
# 3) suma
if getattr(u,"total_base_currency", None):
lines.append(f"{u.total_base_currency:,.2f} {unit}")
if getattr(u, "is_storno", None):
lines.append(f"Puvodni ucet {u.is_storno}")
return "\n".join(lines)
def _matches_filter(self, u: data.UcetSelect, query: str) -> bool:
if not query:
return True
fields = [
getattr(u, "ucislo", ""),
getattr(u, "stul", ""),
getattr(u, "closed_at", ""),
getattr(u, "autor", ""),
getattr(u, "origin", ""),
f"{getattr(u, 'total_base_currency', 0) or 0:.2f}",
]
text = " ".join(str(v or "") for v in fields).lower()
return query.lower() in text
def _on_search_text(self, *_):
self._render_ucty()
def _render_ucty(self):
if not getattr(self, "grid", None):
return
self.grid.clear_widgets()
query = (self.search_input.text or "").strip()
ucty = [u for u in self._all_ucty if self._matches_filter(u, query)]
# seřadit podle čísla účtu vzestupně
ucty_sorted = sorted(
ucty,
key=lambda u: u.ucislo or "", reverse=True )
for u in ucty_sorted:
btn = self._create_ucet_button(u)
if btn:
self.grid.add_widget(btn)
Clock.schedule_once(self._update_scroll, 0)
def _load_ucty(self, ucty: list[data.UcetSelect]):
self._all_ucty = list(ucty or [])
self._render_ucty()
def refresh(self):
ucty = self.get_ucty() or []
self._load_ucty(ucty)
def load_closed_ucty(self):
return [u for u in self.load_stoly() if u.closed]