notbook
42
011 test.py
@@ -56,13 +56,20 @@ class QRPlatbaApp(ctk.CTk):
|
||||
ctk.CTkLabel(pay, text="Vyberte položku k úhradě:",
|
||||
font=("Arial", 12, "bold")).pack(anchor="w", padx=10, pady=(10, 5))
|
||||
|
||||
self.selected_item = ctk.StringVar(value=list(ITEMS.keys())[0])
|
||||
self.combo = ctk.CTkOptionMenu(pay,
|
||||
variable=self.selected_item,
|
||||
values=list(ITEMS.keys()),
|
||||
font=("Arial", 12),
|
||||
command=self.update_amount)
|
||||
# 🏷️ Prepare list like "Očkování chřipka Vaxigrip (600 Kč)"
|
||||
self.display_items = [f"{name} ({price:.0f} Kč)" for name, price in ITEMS.items()]
|
||||
self.item_map = {f"{name} ({price:.0f} Kč)": name for name, price in ITEMS.items()}
|
||||
|
||||
self.selected_item = ctk.StringVar(value=self.display_items[0])
|
||||
self.combo = ctk.CTkOptionMenu(
|
||||
pay,
|
||||
variable=self.selected_item,
|
||||
values=self.display_items,
|
||||
font=("Arial", 12),
|
||||
command=self.update_amount
|
||||
)
|
||||
self.combo.pack(fill="x", padx=10)
|
||||
|
||||
self.amount_label = ctk.CTkLabel(pay, text="", font=("Arial", 12, "italic"))
|
||||
self.amount_label.pack(anchor="e", padx=10, pady=(5, 10))
|
||||
self.update_amount()
|
||||
@@ -80,12 +87,27 @@ class QRPlatbaApp(ctk.CTk):
|
||||
font=("Arial", 10),
|
||||
text_color="#666").pack(side="bottom", pady=(10, 0))
|
||||
|
||||
# ✅ Center window on monitor
|
||||
self.center_window()
|
||||
|
||||
def update_amount(self, _=None):
|
||||
item = self.selected_item.get()
|
||||
display_item = self.selected_item.get()
|
||||
item = self.item_map[display_item]
|
||||
self.amount_label.configure(text=f"Částka: {ITEMS[item]:.2f} Kč")
|
||||
|
||||
def center_window(self):
|
||||
self.update_idletasks() # ensure geometry info is up-to-date
|
||||
width = self.winfo_width()
|
||||
height = self.winfo_height()
|
||||
screen_width = self.winfo_screenwidth()
|
||||
screen_height = self.winfo_screenheight()
|
||||
x = int((screen_width / 2) - (width / 2))
|
||||
y = int((screen_height / 3) - (height / 2))
|
||||
self.geometry(f"{width}x{height}+{x}+{y}")
|
||||
|
||||
def generate_qr(self):
|
||||
item = self.selected_item.get()
|
||||
display_item = self.selected_item.get()
|
||||
item = self.item_map[display_item]
|
||||
spayd = create_spayd(IBAN, ITEMS[item], RODCIS, f"{PRIJMENI} {JMENO} – {item}", CURRENCY)
|
||||
img = qrcode.make(spayd)
|
||||
filename = f"{PRIJMENI}_{JMENO}_{datetime.now():%Y%m%d_%H%M%S}.png"
|
||||
@@ -101,8 +123,8 @@ class QRPlatbaApp(ctk.CTk):
|
||||
self.update_idletasks()
|
||||
self.geometry(f"{self.winfo_reqwidth()}x{self.winfo_reqheight()}")
|
||||
|
||||
messagebox.showinfo("QR Platba vytvořena",
|
||||
f"Soubor uložen jako:\n{out_path}\n\nSPD řetězec:\n{spayd}")
|
||||
# messagebox.showinfo("QR Platba vytvořena",
|
||||
# f"Soubor uložen jako:\n{out_path}\n\nSPD řetězec:\n{spayd}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QRPlatbaApp()
|
||||
|
||||
165
QRPlatbaApp.py
Normal file
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import urllib.parse
|
||||
import qrcode
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from PIL import Image, ImageTk
|
||||
import customtkinter as ctk
|
||||
from tkinter import messagebox
|
||||
|
||||
|
||||
# ================================
|
||||
# ⚙️ Default Configuration
|
||||
# ================================
|
||||
IBAN = "CZ7520100000002800046620"
|
||||
CURRENCY = "CZK"
|
||||
OUTPUT_DIR = Path("QRPlatby")
|
||||
OUTPUT_DIR.mkdir(exist_ok=True)
|
||||
|
||||
# Default values (can be overridden by arguments)
|
||||
PRIJMENI = "Buzalka"
|
||||
JMENO = "Vladimír"
|
||||
RODCIS = "730928104"
|
||||
|
||||
# ================================
|
||||
# 💬 Argument Handling
|
||||
# ================================
|
||||
if len(sys.argv) >= 4:
|
||||
JMENO = sys.argv[1]
|
||||
PRIJMENI = sys.argv[2]
|
||||
RODCIS = sys.argv[3]
|
||||
elif len(sys.argv) == 2 and sys.argv[1] in ("-h", "--help"):
|
||||
print("Usage: QRPlatbaApp.py JMENO PRIJMENI RODCIS")
|
||||
sys.exit(0)
|
||||
|
||||
# ================================
|
||||
# 💉 Items to Pay
|
||||
# ================================
|
||||
ITEMS = {
|
||||
"Očkování chřipka Vaxigrip": 600.00,
|
||||
"Očkování chřipka Efluelda": 1300.00,
|
||||
}
|
||||
|
||||
# ================================
|
||||
# 🧩 Helper
|
||||
# ================================
|
||||
def create_spayd(iban, amount, vs, msg, currency="CZK"):
|
||||
msg_encoded = urllib.parse.quote(msg, safe="$%*+-.:/")
|
||||
return f"SPD*1.0*ACC:{iban}*AM:{amount:.2f}*CC:{currency}*X-VS:{vs}*MSG:{msg_encoded}"
|
||||
|
||||
|
||||
# ================================
|
||||
# 🪟 GUI Class
|
||||
# ================================
|
||||
class QRPlatbaApp(ctk.CTk):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.title("QR Platba – Ordinace MUDr. Buzalková")
|
||||
self.geometry("520x520")
|
||||
self.minsize(480, 480)
|
||||
self.resizable(True, True)
|
||||
|
||||
ctk.set_appearance_mode("light")
|
||||
ctk.set_default_color_theme("blue")
|
||||
|
||||
frame = ctk.CTkFrame(self, corner_radius=10)
|
||||
frame.pack(expand=True, fill="both", padx=20, pady=20)
|
||||
|
||||
ctk.CTkLabel(frame, text="Generátor QR Platby",
|
||||
font=("Arial", 20, "bold")).pack(pady=(10, 20))
|
||||
|
||||
# 👤 Patient Info
|
||||
patient = ctk.CTkFrame(frame, corner_radius=8)
|
||||
patient.pack(fill="x", pady=(0, 20), padx=10)
|
||||
for text in [f"Příjmení: {PRIJMENI}",
|
||||
f"Jméno: {JMENO}",
|
||||
f"Rodné číslo: {RODCIS}"]:
|
||||
ctk.CTkLabel(patient, text=text, font=("Arial", 12)).pack(anchor="w", padx=10, pady=2)
|
||||
|
||||
# 💰 Payment Section
|
||||
pay = ctk.CTkFrame(frame, corner_radius=8)
|
||||
pay.pack(fill="x", pady=(0, 20), padx=10)
|
||||
ctk.CTkLabel(pay, text="Vyberte položku k úhradě:",
|
||||
font=("Arial", 12, "bold")).pack(anchor="w", padx=10, pady=(10, 5))
|
||||
|
||||
self.display_items = [f"{name} ({price:.0f} Kč)" for name, price in ITEMS.items()]
|
||||
self.item_map = {f"{name} ({price:.0f} Kč)": name for name, price in ITEMS.items()}
|
||||
|
||||
self.selected_item = ctk.StringVar(value=self.display_items[0])
|
||||
self.combo = ctk.CTkOptionMenu(
|
||||
pay,
|
||||
variable=self.selected_item,
|
||||
values=self.display_items,
|
||||
font=("Arial", 12),
|
||||
command=self.update_amount
|
||||
)
|
||||
self.combo.pack(fill="x", padx=10)
|
||||
|
||||
self.amount_label = ctk.CTkLabel(pay, text="", font=("Arial", 12, "italic"))
|
||||
self.amount_label.pack(anchor="e", padx=10, pady=(5, 10))
|
||||
self.update_amount()
|
||||
|
||||
ctk.CTkButton(frame, text="Vytvořit QR Platbu",
|
||||
font=("Arial", 13, "bold"),
|
||||
height=40,
|
||||
command=self.generate_qr).pack(pady=10)
|
||||
|
||||
self.qr_label = ctk.CTkLabel(frame, text="")
|
||||
self.qr_label.pack(pady=15)
|
||||
|
||||
ctk.CTkLabel(frame,
|
||||
text="© Ordinace MUDr. Buzalková | QR Platba dle ČBA v1.2",
|
||||
font=("Arial", 10),
|
||||
text_color="#666").pack(side="bottom", pady=(10, 0))
|
||||
|
||||
self.center_window()
|
||||
|
||||
# ================================
|
||||
# 🪟 Center Window
|
||||
# ================================
|
||||
def center_window(self):
|
||||
self.update_idletasks()
|
||||
width = self.winfo_width()
|
||||
height = self.winfo_height()
|
||||
screen_width = self.winfo_screenwidth()
|
||||
screen_height = self.winfo_screenheight()
|
||||
x = int((screen_width / 2) - (width / 2))
|
||||
y = int((screen_height / 2) - (height / 2))
|
||||
self.geometry(f"{width}x{height}+{x}+{y}")
|
||||
|
||||
# ================================
|
||||
# 💸 Update and Generate
|
||||
# ================================
|
||||
def update_amount(self, _=None):
|
||||
display_item = self.selected_item.get()
|
||||
item = self.item_map[display_item]
|
||||
self.amount_label.configure(text=f"Částka: {ITEMS[item]:.2f} Kč")
|
||||
|
||||
def generate_qr(self):
|
||||
display_item = self.selected_item.get()
|
||||
item = self.item_map[display_item]
|
||||
spayd = create_spayd(IBAN, ITEMS[item], RODCIS, f"{PRIJMENI} {JMENO} – {item}", CURRENCY)
|
||||
img = qrcode.make(spayd)
|
||||
filename = f"{PRIJMENI}_{JMENO}_{datetime.now():%Y%m%d_%H%M%S}.png"
|
||||
out_path = OUTPUT_DIR / filename
|
||||
img.save(out_path)
|
||||
|
||||
img_resized = img.resize((300, 300))
|
||||
qr_tk = ImageTk.PhotoImage(img_resized)
|
||||
self.qr_label.configure(image=qr_tk)
|
||||
self.qr_label.image = qr_tk
|
||||
|
||||
self.update_idletasks()
|
||||
self.geometry(f"{self.winfo_reqwidth()}x{self.winfo_reqheight()}")
|
||||
self.center_window()
|
||||
|
||||
|
||||
# ================================
|
||||
# 🚀 Main
|
||||
# ================================
|
||||
if __name__ == "__main__":
|
||||
app = QRPlatbaApp()
|
||||
app.mainloop()
|
||||
38
QRPlatbaApp.spec
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['QRPlatbaApp.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
[],
|
||||
name='QRPlatbaApp',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
BIN
QRPlatby/Buzalka_Vladimír_20251105_183918.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_184447.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_185339.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_194921.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_195326.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_195354.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_202608.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251105_202617.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_061536.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_062033.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_062215.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_062224.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_062231.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
QRPlatby/Buzalka_Vladimír_20251106_062235.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
4445
build/QRPlatbaApp/Analysis-00.toc
Normal file
2820
build/QRPlatbaApp/EXE-00.toc
Normal file
2798
build/QRPlatbaApp/PKG-00.toc
Normal file
BIN
build/QRPlatbaApp/PYZ-00.pyz
Normal file
1393
build/QRPlatbaApp/PYZ-00.toc
Normal file
BIN
build/QRPlatbaApp/QRPlatbaApp.pkg
Normal file
BIN
build/QRPlatbaApp/base_library.zip
Normal file
59
build/QRPlatbaApp/warn-QRPlatbaApp.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
This file lists modules PyInstaller was not able to find. This does not
|
||||
necessarily mean this module is required for running your program. Python and
|
||||
Python 3rd-party packages include a lot of conditional or optional modules. For
|
||||
example the module 'ntpath' only exists on Windows, whereas the module
|
||||
'posixpath' only exists on Posix systems.
|
||||
|
||||
Types if import:
|
||||
* top-level: imported at the top-level - look at these first
|
||||
* conditional: imported within an if-statement
|
||||
* delayed: imported within a function
|
||||
* optional: imported within a try-except-statement
|
||||
|
||||
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
||||
tracking down the missing module yourself. Thanks!
|
||||
|
||||
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), setuptools._distutils.util (delayed, conditional, optional), netrc (delayed, conditional), getpass (delayed), setuptools._vendor.backports.tarfile (optional), setuptools._distutils.archive_util (optional), http.server (delayed, optional)
|
||||
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), setuptools._vendor.backports.tarfile (optional), setuptools._distutils.archive_util (optional)
|
||||
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
|
||||
missing module named fcntl - imported by subprocess (optional)
|
||||
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
missing module named posix - imported by os (conditional, optional), shutil (conditional), importlib._bootstrap_external (conditional), posixpath (optional)
|
||||
missing module named resource - imported by posix (top-level)
|
||||
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
|
||||
missing module named _scproxy - imported by urllib.request (conditional)
|
||||
missing module named termios - imported by getpass (optional), tty (top-level)
|
||||
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
||||
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
||||
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named pyimod02_importers - imported by U:\PycharmProjects\FIO\.venv\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
|
||||
missing module named typing_extensions.Buffer - imported by setuptools._vendor.typing_extensions (top-level), setuptools._vendor.wheel.wheelfile (conditional)
|
||||
missing module named typing_extensions.Literal - imported by setuptools._vendor.typing_extensions (top-level), setuptools.config._validate_pyproject.formats (conditional)
|
||||
missing module named typing_extensions.Self - imported by setuptools._vendor.typing_extensions (top-level), setuptools.config.expand (conditional), setuptools.config.pyprojecttoml (conditional), setuptools.config._validate_pyproject.error_reporting (conditional)
|
||||
missing module named typing_extensions.deprecated - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.sysconfig (conditional), setuptools._distutils.command.bdist (conditional)
|
||||
missing module named typing_extensions.TypeAlias - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.compilers.C.base (conditional), setuptools._reqs (conditional), setuptools.warnings (conditional), setuptools._path (conditional), setuptools._distutils.dist (conditional), setuptools.config.setupcfg (conditional), setuptools.config._apply_pyprojecttoml (conditional), setuptools.dist (conditional), setuptools.command.bdist_egg (conditional), setuptools.compat.py311 (conditional)
|
||||
missing module named typing_extensions.Unpack - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.util (conditional), setuptools._distutils.compilers.C.base (conditional), setuptools._distutils.cmd (conditional)
|
||||
missing module named typing_extensions.TypeVarTuple - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.util (conditional), setuptools._distutils.compilers.C.base (conditional), setuptools._distutils.cmd (conditional)
|
||||
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
||||
missing module named vms_lib - imported by platform (delayed, optional)
|
||||
missing module named 'java.lang' - imported by platform (delayed, optional)
|
||||
missing module named java - imported by platform (delayed)
|
||||
missing module named _winreg - imported by platform (delayed, optional)
|
||||
missing module named usercustomize - imported by site (delayed, optional)
|
||||
missing module named sitecustomize - imported by site (delayed, optional)
|
||||
missing module named readline - imported by site (delayed, optional), rlcompleter (optional)
|
||||
missing module named _typeshed - imported by setuptools._distutils.dist (conditional), setuptools.glob (conditional), setuptools.compat.py311 (conditional)
|
||||
missing module named _manylinux - imported by packaging._manylinux (delayed, optional), setuptools._vendor.packaging._manylinux (delayed, optional), setuptools._vendor.wheel.vendored.packaging._manylinux (delayed, optional)
|
||||
missing module named importlib_resources - imported by setuptools._vendor.jaraco.text (optional)
|
||||
missing module named trove_classifiers - imported by setuptools.config._validate_pyproject.formats (optional)
|
||||
missing module named PyObjCTools - imported by darkdetect._mac_detect (optional)
|
||||
missing module named Foundation - imported by darkdetect._mac_detect (optional)
|
||||
missing module named numpy - imported by PIL._typing (conditional, optional)
|
||||
missing module named olefile - imported by PIL.FpxImagePlugin (top-level), PIL.MicImagePlugin (top-level)
|
||||
missing module named defusedxml - imported by PIL.Image (optional)
|
||||
missing module named png - imported by qrcode.compat.png (optional)
|
||||
22568
build/QRPlatbaApp/xref-QRPlatbaApp.html
Normal file
BIN
dist/QRPlatbaApp.exe
vendored
Normal file
BIN
fio_payment.png
Normal file
|
After Width: | Height: | Size: 898 B |
BIN
fio_qr_correct.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
fio_qr_valid_v12.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
qrplatba_ok.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |