First Upload
commit
d5a8c8e9f4
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.12 (Shopware-API)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.12 (Shopware-API)" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Shopware-API.iml" filepath="$PROJECT_DIR$/.idea/Shopware-API.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
%PDF-1.3
|
||||
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R /F2 3 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/Contents 8 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 7 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/PageMode /UseNone /Pages 7 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/Author (anonymous) /CreationDate (D:20250217154506+01'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20250217154506+01'00') /Producer (ReportLab PDF Library - www.reportlab.com)
|
||||
/Subject (unspecified) /Title (Lieferschein 17.02.2025) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Count 1 /Kids [ 4 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 582
|
||||
>>
|
||||
stream
|
||||
Gau0@b>,r/&A7TLHNYUG]sd6[,GK.N!mq9+>ccM4TI(f%'mr2_*c5S"LJ"4-OlFS[B%Ji95hnf/k9:/@9]>o<!_#XeJF\L`H4/3oW*2]aPA37;E48R]$:,d]"O\9Mk:4gNlKgFX0A;YK=.L'ROM4#,]&ak07u'aW2:p?B<j,O><.4jI7Kaq]./*IUPY]eVQb)0,ekVrZN._a#+HBE3_ei$>K5.CPg8Bp0<=_#mOWiRQ,I*i0=rL\4qVjb[P=F?@[bAN\2MF%R.Crp@Cm[*FR5(Z]/+]K(;PQf7OMKX4Ksh(9.a00pk]=5\0^fWFpJKKEO32"5Yjc)XQg9>GrZR/)_>NP43kO/5Q&+WXS9<a2#U^W`&g[iH,9a`1Gc67,Me4FhIN`(bb7BFGj5M!`:ILG'@J(I8cOQL1ld$XT/[4a\=CD-C9/;jj,koAL_SX:l,alb=82AqGm0dNA-d^qS.(neTc"(U'\P'<EU.N,C4;ZAqWF[a4(^E`g8O!jWRG$3:bD.u6e"tr1D=u1_1?*b<[;_052\'UHbW.3qbQrsK.$TK4*.%oi+Q5;/4LL:0KYu1rVKfuB~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 9
|
||||
0000000000 65535 f
|
||||
0000000073 00000 n
|
||||
0000000114 00000 n
|
||||
0000000221 00000 n
|
||||
0000000333 00000 n
|
||||
0000000536 00000 n
|
||||
0000000604 00000 n
|
||||
0000000915 00000 n
|
||||
0000000974 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<52cc85184a6e7bde8ef927cb4ba48ccd><52cc85184a6e7bde8ef927cb4ba48ccd>]
|
||||
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
|
||||
|
||||
/Info 6 0 R
|
||||
/Root 5 0 R
|
||||
/Size 9
|
||||
>>
|
||||
startxref
|
||||
1646
|
||||
%%EOF
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
import os
|
||||
import customtkinter as ctk
|
||||
import winreg
|
||||
from PIL import Image
|
||||
import webbrowser
|
||||
|
||||
REG_PATH = r"Software\ShopwareDeliver"
|
||||
|
||||
def rerun():
|
||||
"""Löscht Registry-Werte und ruft run() auf, falls Werte fehlen"""
|
||||
try:
|
||||
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, REG_PATH, 0, winreg.KEY_SET_VALUE) as key:
|
||||
all_deleted = True # Flag, um zu prüfen, ob alle Werte gelöscht wurden
|
||||
|
||||
for name in ["CLIENT_ID", "CLIENT_SECRET", "API_URL"]:
|
||||
try:
|
||||
winreg.DeleteValue(key, name)
|
||||
print(f"✅ {name} wurde gelöscht.")
|
||||
except FileNotFoundError:
|
||||
print(f"⚠️ {name} war nicht vorhanden.")
|
||||
all_deleted = False # Mindestens ein Wert fehlte bereits
|
||||
|
||||
if all_deleted:
|
||||
print("✅ Alle Werte erfolgreich gelöscht.")
|
||||
run() # Falls alles erfolgreich gelöscht wurde, rufe run() auf
|
||||
else:
|
||||
print("⚠️ Einige Werte waren nicht vorhanden, run() wird nicht aufgerufen.")
|
||||
|
||||
except FileNotFoundError:
|
||||
print("⚠️ Fehler: Registry-Schlüssel nicht gefunden!")
|
||||
run() # Falls die gesamte Registry fehlt, rufe run() auf
|
||||
|
||||
|
||||
def run():
|
||||
REG_PATH = r"Software\ShopwareDeliver"
|
||||
|
||||
def get_registry_value(name):
|
||||
"""Liest einen Wert aus der Windows-Registry"""
|
||||
try:
|
||||
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, REG_PATH, 0, winreg.KEY_READ) as key:
|
||||
value, _ = winreg.QueryValueEx(key, name)
|
||||
return value
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
|
||||
def set_registry_value(name, value):
|
||||
"""Speichert einen Wert in der Windows-Registry"""
|
||||
with winreg.CreateKey(winreg.HKEY_CURRENT_USER, REG_PATH) as key:
|
||||
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value)
|
||||
|
||||
def open_link(event=None):
|
||||
webbrowser.open("https://itdata-gera.de")
|
||||
|
||||
# Prüfe, ob die Werte existieren
|
||||
CLIENT_ID = get_registry_value("CLIENT_ID")
|
||||
CLIENT_SECRET = get_registry_value("CLIENT_SECRET")
|
||||
API_URL = get_registry_value("API_URL")
|
||||
|
||||
# Falls Werte fehlen, öffne das Eingabe-Fenster
|
||||
if not CLIENT_ID or not CLIENT_SECRET or not API_URL:
|
||||
|
||||
class SecretInputApp(ctk.CTk):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.title("API-Konfiguration")
|
||||
self.geometry("400x300")
|
||||
|
||||
ctk.CTkLabel(self, text="Shopware Deliver", font=("Arial", 20)).pack(pady=5)
|
||||
ctk.CTkLabel(self, text="Bitte geben Sie die API-Daten ein:", font=("Arial", 16)).pack(pady=10)
|
||||
|
||||
self.client_id_entry = ctk.CTkEntry(self, placeholder_text="Client ID")
|
||||
self.client_id_entry.pack(pady=5, padx=10, fill="x")
|
||||
|
||||
self.client_secret_entry = ctk.CTkEntry(self, placeholder_text="Client Secret", show="*")
|
||||
self.client_secret_entry.pack(pady=5, padx=10, fill="x")
|
||||
|
||||
self.api_url_entry = ctk.CTkEntry(self, placeholder_text="Shopware URL")
|
||||
self.api_url_entry.pack(pady=5, padx=10, fill="x")
|
||||
|
||||
self.save_button = ctk.CTkButton(self, text="Speichern", command=self.save_keys)
|
||||
self.save_button.pack(pady=20)
|
||||
|
||||
def save_keys(self):
|
||||
client_id = self.client_id_entry.get()
|
||||
client_secret = self.client_secret_entry.get()
|
||||
api_url = self.api_url_entry.get()
|
||||
|
||||
if client_id and client_secret and api_url:
|
||||
# Speichere die Werte in der Windows-Registry
|
||||
set_registry_value("CLIENT_ID", client_id)
|
||||
set_registry_value("CLIENT_SECRET", client_secret)
|
||||
set_registry_value("API_URL", api_url)
|
||||
|
||||
self.destroy() # Fenster schließen nach dem Speichern
|
||||
else:
|
||||
ctk.CTkLabel(self, text="Alle Felder müssen ausgefüllt sein!", text_color="red").pack(pady=5)
|
||||
|
||||
# Starte die GUI
|
||||
app = SecretInputApp()
|
||||
app.mainloop()
|
||||
|
||||
# Jetzt sind die Werte sicher gespeichert und können im restlichen Skript genutzt werden
|
||||
CLIENT_ID = get_registry_value("CLIENT_ID")
|
||||
CLIENT_SECRET = get_registry_value("CLIENT_SECRET")
|
||||
API_URL = get_registry_value("API_URL")
|
||||
|
||||
return CLIENT_ID, CLIENT_SECRET, API_URL
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
import tkinter
|
||||
from PIL import Image
|
||||
import requests
|
||||
import webbrowser
|
||||
import customtkinter as ctk
|
||||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.pdfgen import canvas
|
||||
from datetime import datetime
|
||||
import datetime
|
||||
import check_api
|
||||
|
||||
STATUS_PAID = "in_progress"
|
||||
keys = check_api.run()
|
||||
CLIENT_ID = keys[0]
|
||||
CLIENT_SECRET = keys[1]
|
||||
SHOPWARE_URL = keys[2]
|
||||
|
||||
current_order_id = None
|
||||
|
||||
def get_order_line_items(access_token, order_id):
|
||||
headers = {
|
||||
"sw-access-key": CLIENT_ID,
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
items_url = f"{SHOPWARE_URL}/api/order/{order_id}/line-items"
|
||||
response = requests.get(items_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()["data"]
|
||||
|
||||
def get_order_customer(access_token, customer_id):
|
||||
headers = {
|
||||
"sw-access-key": CLIENT_ID,
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
customer_url = f"{SHOPWARE_URL}/api/order-customer/{customer_id}"
|
||||
response = requests.get(customer_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()["data"]
|
||||
|
||||
def get_order_billing_address(access_token, order_id):
|
||||
headers = {
|
||||
"sw-access-key": CLIENT_ID,
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
address_url = f"{SHOPWARE_URL}/api/order/{order_id}/billing-address/"
|
||||
response = requests.get(address_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()["data"][0]
|
||||
|
||||
def get_access_token():
|
||||
token_url = f"{SHOPWARE_URL}/api/oauth/token"
|
||||
data = {
|
||||
"client_id": CLIENT_ID,
|
||||
"client_secret": CLIENT_SECRET,
|
||||
"grant_type": "client_credentials"
|
||||
}
|
||||
response = requests.post(token_url, data=data)
|
||||
response.raise_for_status()
|
||||
return response.json()["access_token"]
|
||||
|
||||
def get_paid_orders(access_token):
|
||||
headers = {
|
||||
"sw-access-key": CLIENT_ID,
|
||||
"authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
orders_url = f"{SHOPWARE_URL}/api/search/order"
|
||||
query = {
|
||||
"limit": 100,
|
||||
"page": 1,
|
||||
"filter": [{
|
||||
"type": "equals",
|
||||
"field": "stateMachineState.technicalName",
|
||||
"value": STATUS_PAID
|
||||
}]
|
||||
}
|
||||
response = requests.post(orders_url, headers=headers, json=query)
|
||||
response.raise_for_status()
|
||||
return response.json()["data"]
|
||||
|
||||
def get_order_details(access_token, order_id):
|
||||
headers = {
|
||||
"sw-access-key": CLIENT_ID,
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
items_url = f"{SHOPWARE_URL}/api/order/{order_id}/line-items"
|
||||
address_url = f"{SHOPWARE_URL}/api/order/{order_id}/billing-address/"
|
||||
|
||||
response_items = requests.get(items_url, headers=headers)
|
||||
response_address = requests.get(address_url, headers=headers)
|
||||
|
||||
response_items.raise_for_status()
|
||||
response_address.raise_for_status()
|
||||
|
||||
return response_items.json()["data"], response_address.json()["data"][0]
|
||||
|
||||
def show_order_details(event):
|
||||
global current_order_id
|
||||
|
||||
selected_item = tree_orders.focus()
|
||||
if not selected_item:
|
||||
return
|
||||
|
||||
values = tree_orders.item(selected_item, "values")
|
||||
order_number = values[0]
|
||||
customer_name = values[1]
|
||||
|
||||
access_token = get_access_token()
|
||||
orders = get_paid_orders(access_token)
|
||||
selected_order = next((o for o in orders if o['attributes']['orderNumber'] == order_number), None)
|
||||
|
||||
if selected_order:
|
||||
order_id = selected_order['id']
|
||||
current_order_id = order_id
|
||||
|
||||
product_line, billing_address = get_order_details(access_token, order_id)
|
||||
|
||||
frame_orders.pack_forget()
|
||||
tree_details.delete(*tree_details.get_children())
|
||||
|
||||
for product in product_line:
|
||||
label = product['attributes'].get('label', 'Unbekanntes Produkt')
|
||||
quantity = product['attributes']['quantity']
|
||||
price = product['attributes']['totalPrice']
|
||||
tree_details.insert("", "end", values=(label, quantity, f"{price:.2f} €"))
|
||||
|
||||
label_details.configure(text=f"Bestellung: {order_number} - {customer_name}")
|
||||
frame_details.pack(fill="both", expand=True)
|
||||
|
||||
def back_to_orders():
|
||||
frame_details.pack_forget()
|
||||
frame_orders.pack(fill="both", expand=True)
|
||||
|
||||
def print_single_order():
|
||||
if not current_order_id:
|
||||
messagebox.showerror("Fehler", "Keine Bestellung ausgewählt!")
|
||||
return
|
||||
|
||||
access_token = get_access_token()
|
||||
orders = get_paid_orders(access_token)
|
||||
selected_order = next((o for o in orders if o['id'] == current_order_id), None)
|
||||
|
||||
if selected_order:
|
||||
filename = generate_combined_pdf([selected_order], access_token)
|
||||
messagebox.showinfo("Erfolg", f"Lieferschein {filename} wurde erstellt!")
|
||||
else:
|
||||
messagebox.showerror("Fehler", "Bestellung nicht gefunden!")
|
||||
|
||||
def generate_combined_pdf(orders, access_token):
|
||||
current_date = datetime.datetime.today().strftime("%d.%m.%Y")
|
||||
filename = f"Lieferschein_{current_date}.pdf"
|
||||
|
||||
pdf = canvas.Canvas(filename, pagesize=A4)
|
||||
pdf.setTitle(f"Lieferschein {current_date}")
|
||||
pdf.setFont("Helvetica-Bold", 16)
|
||||
pdf.drawString(50, 800, "Sammel-Lieferschein")
|
||||
|
||||
pdf.setFont("Helvetica", 12)
|
||||
pdf.drawString(50, 780, f"Erstellt am: {current_date}")
|
||||
|
||||
y_position = 750
|
||||
for order in orders:
|
||||
try:
|
||||
customer_id = order["relationships"]["orderCustomer"]["data"]["id"]
|
||||
customer = get_order_customer(access_token, customer_id)
|
||||
billing_address = get_order_billing_address(access_token, order["id"])
|
||||
product_line = get_order_line_items(access_token, order["id"])
|
||||
|
||||
# Bestell-Header
|
||||
pdf.setFont("Helvetica-Bold", 12)
|
||||
pdf.drawString(50, y_position, f"Bestellnummer: {order['attributes']['orderNumber']}")
|
||||
|
||||
date_obj = datetime.datetime.strptime(order['attributes']['orderDate'], "%Y-%m-%dT%H:%M:%S.%f%z")
|
||||
date_str = date_obj.strftime("%d.%m.%Y")
|
||||
pdf.setFont("Helvetica", 10)
|
||||
pdf.drawString(50, y_position - 20, f"Bestelldatum: {date_str}")
|
||||
|
||||
# Rahmen um Lieferadresse
|
||||
pdf.setStrokeColorRGB(0, 0, 0) # Schwarz
|
||||
#pdf.rect(45, y_position - 110, 300, 80, stroke=1, fill=0) # Rechteck um Adresse
|
||||
|
||||
# Lieferadresse
|
||||
pdf.setFont("Helvetica-Bold", 10)
|
||||
pdf.drawString(50, y_position - 100, "Lieferadresse:")
|
||||
pdf.setFont("Helvetica", 10)
|
||||
pdf.drawString(50, y_position - 120, f"{customer['attributes']['firstName']} {customer['attributes']['lastName']}")
|
||||
pdf.drawString(50, y_position - 140, f"{billing_address['attributes']['street']}")
|
||||
pdf.drawString(50, y_position - 160, f"{billing_address['attributes']['zipcode']} {billing_address['attributes']['city']}")
|
||||
|
||||
y_position -= 180 # Platz nach Adresse
|
||||
|
||||
# Produktliste
|
||||
for product in product_line:
|
||||
pdf.rect(50, y_position - 2, 10, 10, stroke=1, fill=0) # Checkbox für Abhaken
|
||||
label = product['attributes'].get('label', 'Unbekanntes Produkt')
|
||||
product_number = product['attributes']['payload'].get('productNumber', 'Keine Nummer')
|
||||
quantity = product['attributes']['quantity']
|
||||
price = product['attributes']['totalPrice']
|
||||
|
||||
pdf.drawString(70, y_position, f"{label}")
|
||||
pdf.drawString(250, y_position, f"{product_number}")
|
||||
pdf.drawString(350, y_position, f"{quantity}")
|
||||
pdf.drawString(400, y_position, f"{price:.2f} €")
|
||||
|
||||
y_position -= 20
|
||||
|
||||
# Falls die Seite voll ist, neue Seite beginnen
|
||||
if y_position < 100:
|
||||
pdf.showPage()
|
||||
y_position = 800
|
||||
|
||||
y_position -= 40 # Platz nach jeder Bestellung
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Erstellen des Lieferscheins für Bestellung {order['attributes']['orderNumber']}: {str(e)}")
|
||||
|
||||
pdf.save()
|
||||
print(f"Lieferschein gespeichert: {filename}")
|
||||
|
||||
return filename
|
||||
|
||||
def print_all_orders():
|
||||
access_token = get_access_token()
|
||||
orders = get_paid_orders(access_token)
|
||||
|
||||
if not orders:
|
||||
messagebox.showinfo("Info", "Keine Bestellungen gefunden.")
|
||||
return
|
||||
|
||||
filename = generate_combined_pdf(orders, access_token)
|
||||
messagebox.showinfo("Erfolg", f"Gesammelter Lieferschein {filename} wurde erstellt!")
|
||||
|
||||
def update_table():
|
||||
access_token = get_access_token()
|
||||
orders = get_paid_orders(access_token)
|
||||
# Tabelle leeren
|
||||
for row in tree_orders.get_children():
|
||||
tree_orders.delete(row)
|
||||
|
||||
for order in orders:
|
||||
order_number = order['attributes']['orderNumber']
|
||||
_, billing_address = get_order_details(access_token, order['id'])
|
||||
|
||||
tree_orders.insert("", "end", values=(
|
||||
order_number,
|
||||
f"{billing_address['attributes']['firstName']} {billing_address['attributes']['lastName']}",
|
||||
billing_address['attributes']['street'],
|
||||
f"{billing_address['attributes']['zipcode']} {billing_address['attributes']['city']}"
|
||||
))
|
||||
|
||||
|
||||
def open_link(event=None):
|
||||
webbrowser.open("https://itdata-gera.de")
|
||||
|
||||
def execute_with_error_handling(func, *args, **kwargs):
|
||||
try:
|
||||
func(*args, **kwargs) # Die gewünschte Funktion ausführen
|
||||
except Exception as e:
|
||||
root.after(0, show_error_message, str(e)) # Fehler in GUI anzeigen
|
||||
|
||||
# GUI-Fehlermeldung anzeigen
|
||||
def show_error_message(error_text):
|
||||
tkinter.messagebox.showerror("Fehler", f"Ein Fehler ist aufgetreten:\n{error_text}")
|
||||
|
||||
# GUI-Erstellung
|
||||
root = ctk.CTk()
|
||||
root.title("Lieferschein-Drucker")
|
||||
root.resizable(False, False)
|
||||
|
||||
window_width = 900
|
||||
window_height = 500
|
||||
|
||||
# Bildschirmgröße abrufen
|
||||
screen_width = root.winfo_screenwidth()
|
||||
screen_height = root.winfo_screenheight()
|
||||
|
||||
# Position berechnen (Mitte des Bildschirms)
|
||||
x_position = (screen_width // 2) - (window_width // 2)
|
||||
y_position = (screen_height // 2) - (window_height // 2)
|
||||
|
||||
# Fenstergröße & Position setzen
|
||||
root.geometry(f"{window_width}x{window_height}+{x_position}+{y_position}")
|
||||
|
||||
# **Bestellübersicht**
|
||||
frame_orders = ctk.CTkFrame(root)
|
||||
button_all_print = ctk.CTkButton(frame_orders, text="API ändern", command=lambda: execute_with_error_handling(check_api.rerun),fg_color="#2b2b2b",text_color="white",anchor=tkinter.RIGHT)
|
||||
button_all_print.pack(pady=5,anchor="ne")
|
||||
|
||||
label_orders = ctk.CTkLabel(frame_orders, text=f"Bezahlte Bestellungen - {datetime.datetime.now().strftime("%d.%m.%Y")}", font=("Helvetica", 15))
|
||||
label_orders.pack(pady=5)
|
||||
|
||||
columns_orders = ("Bestellnummer", "Kunde", "Straße", "PLZ/Stadt")
|
||||
tree_orders = ttk.Treeview(frame_orders, columns=columns_orders, show="headings", cursor="hand2")
|
||||
for col in columns_orders:
|
||||
tree_orders.heading(col, text=col)
|
||||
tree_orders.column(col, width=150)
|
||||
tree_orders.pack(expand=True, fill="both")
|
||||
tree_orders.bind("<<TreeviewSelect>>", show_order_details)
|
||||
|
||||
button_update = ctk.CTkButton(frame_orders, text="Bestellungen laden", command=lambda: execute_with_error_handling(update_table), fg_color="lightblue",text_color="black",anchor=tkinter.RIGHT)
|
||||
button_update.pack(side="left",pady=5,padx=10)
|
||||
|
||||
logo = ctk.CTkImage(dark_image=Image.open('logo.png'),size=(130,30))
|
||||
logo_label = ctk.CTkLabel(root, text="", image=logo, fg_color="#2b2b2b",cursor="hand2")
|
||||
logo_label.bind("<Button-1>", open_link)
|
||||
logo_label.place(relx=0.5, rely=1.0, anchor="s",y=-15)
|
||||
|
||||
button_all_print = ctk.CTkButton(frame_orders, text="Gesammelten Lieferschein drucken", command=lambda: execute_with_error_handling(print_all_orders),fg_color="orange",text_color="black")
|
||||
button_all_print.pack(side="right",pady=15, padx=10)
|
||||
|
||||
frame_orders.pack(fill="both", expand=True)
|
||||
|
||||
# **Detailansicht**
|
||||
frame_details = ctk.CTkFrame(root)
|
||||
label_details = ctk.CTkLabel(frame_details, text="", font=("Helvetica", 12))
|
||||
label_details.pack(pady=5)
|
||||
|
||||
columns_details = ("Produkt", "Anzahl", "Preis")
|
||||
tree_details = ttk.Treeview(frame_details, columns=columns_details, show="headings")
|
||||
for col in columns_details:
|
||||
tree_details.heading(col, text=col)
|
||||
tree_details.pack(expand=True, fill="both")
|
||||
|
||||
button_back = ctk.CTkButton(frame_details, text="Zurück", command=back_to_orders)
|
||||
button_back.pack(side="left", padx=20, pady=15)
|
||||
|
||||
logo_label_1 = ctk.CTkLabel(root, text="", image=logo, fg_color="#2b2b2b",cursor="hand2")
|
||||
logo_label_1.bind("<Button-1>", open_link)
|
||||
logo_label_1.place(relx=0.5, rely=1.0, anchor="s",y=-15)
|
||||
|
||||
button_print = ctk.CTkButton(frame_details, text="Diese Bestellung drucken", command=print_single_order, fg_color="lightgreen", text_color="black")
|
||||
button_print.pack(side="right", padx=20,pady=15)
|
||||
|
||||
# Error Handling für Timeout
|
||||
root.after(100, lambda: execute_with_error_handling(update_table))
|
||||
root.mainloop()
|
||||
Loading…
Reference in New Issue