Menü wird nur beim ersten mal wählen ausgegeben, Ausgabefehler

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
marco2810
User
Beiträge: 1
Registriert: Mittwoch 15. Mai 2024, 18:27

Hallo allerseits,
ich habe folgendes Problem.
Wenn ich im ersten Menü die Funktion 1. auswähle, im 2. Menü auch dann funktioniert alles. Wähle ich aber nun anschließend im 1. Menü wieder die 1, dann wird mir das 2. Menü nicht angezeigt.
Der Fehler tritt komischerweise nicht immer auf, ich finde leider nicht heraus woran es liegt.
Wäre toll wenn mir da jemand helfen könnte, danke schonmal!

Code: Alles auswählen

# Funktion zur Berechnung der PayPal-Gebühren
def gebühr_berechnen(zahlungsart, betrag):
    # Gebührenraten je nach Zahlungstyp festlegen, vorderer Wert Prozentsatz, hinterer Wert fixer Betrag 
    gebührenrate = {
        "1": (0.0249, 0.35),   # Waren/Dienstleistungen
        "2": (0, 0),           # Freunde
        "3": (0.0249, 0.35),   # Spenden sammeln
        "4": (0.0499, 0.09)    # Mikrozahlung (Beträge bis 5€)
    }
    
    # Wenn Zahlungstyp nicht gefunden wird, gib None zurück
    if zahlungsart not in gebührenrate:
        return None, None
    
    # Gebühr berechnen
    gebühr_prozentsatz, fixe_gebühr = gebührenrate[zahlungsart]
    gebühr = betrag * gebühr_prozentsatz + fixe_gebühr
    gesamt_betrag = betrag - gebühr
    return round (gebühr, 2), round (gesamt_betrag, 2) 

# Hauptprogramm
def main():
    print("Willkommen beim PayPal-Gebührenrechner!")
    while True:
        print("\nMenü:")
        print("1. Gebühr berechnen")
        print("2. Gespeicherte Berechnungen anzeigen")
        print("3. Gespeicherte Berechnungen löschen")
        print("4. Programm beenden")
        menüwahl = input("Bitte wählen Sie die gewünschte Funktion durch eingabe von 1, 2, 3 oder 4: ")
        
        if menüwahl == "1":
            display_payment_options()
            payment_choice = input("Bitte wählen Sie die Art der Zahlung durch Eingabe von 1, 2, 3 oder 4: ")
            betrag = float(input("Bitte geben Sie den € Betrag ein im Format zz.xx (z bis max. 5 stellen):"))
            
            gebühr, gesamt_betrag = gebühr_berechnen(payment_choice, betrag)
            if gebühr is not None:
                save_transaction(payment_choice, betrag)
                display_results(gebühr, gesamt_betrag)
            else:
                print("Ungültiger Zahlungstyp. Bitte geben Sie eine gültige Zahlungsoption ein (1, 2, 3 oder 4).")
        
        elif menüwahl == "2":
            retrieve_transactions()

        elif menüwahl == "3":
            transaction_id = input("Bitte gibt die ID der Berechnung ein, die du löschen möchtest. ")
            delete_transaction(transaction_id)
        
        elif menüwahl == "4":
            print("Programm wird beendet.")
            break
        
        else:
            print("Ungültige Eingabe")

# Funktion zur Ausgabe der Zahlungstyp-Optionen
def display_payment_options():
    print("Zahlungstypen:")
    print("1. Waren/Dienstleistungen")
    print("2. Freunde")
    print("3. Spenden sammeln")
    print("4. Mikrozahlung")

# Funktion zur Ausgabe der Ergebnisse
def display_results(gebühr, gesamt_betrag):
    if gebühr is not None:
        print("PayPal-Gebühr:", gebühr, "€")
        print("Betrag nach Abzug der Gebühr:", gesamt_betrag, "€")
    else:
        print("Ungültiger Zahlungstyp.")

# Funktion zur Speicherung der Berechnung in der Datenbank
def save_transaction(zahlungsart, betrag):
    try:
        # SQL-Befehl zum Speichern einer Berechnung
        sql = "INSERT INTO transactions (zahlungsart, betrag) VALUES (%s, %s)"
        val = (zahlungsart, betrag)
        cursor.execute(sql, val)
        connection.commit()  # Änderungen in der Datenbank speichern
        print("Berechnung erfolgreich gespeichert.")
    except mysql.connector.Error as err:
        print(f"Fehler beim Speichern der Berechnung: {err}")

# Funktion zur Abfrage der gespeicherten Berechnungen aus der Datenbank
def retrieve_transactions():
    try:
        # SQL-Befehl zum Abrufen aller Berechnungen
        sql = "SELECT * FROM transactions"
        cursor.execute(sql)
        transactions = cursor.fetchall() 
        print("Gespeicherte Berechnungen:")
        for transaction in transactions:
            print("ID:", transaction[0])
            print("Art der Zahlung:", transaction[1])
            print("Betrag:", transaction[2])
            print("--------------------------")
    except mysql.connector.Error as err:
        print(f"Fehler beim Abrufen der Berechnungen: {err}")

# Funktion zum löschen von gespeicherten Zahlungen
def delete_transaction(transaction_id):
    try:
        sql = "DELETE FROM transactions WHERE id = %s"
        val = (transaction_id,)
        cursor.execute(sql, val)
        connection.commit()
        print("Gespeicherte Berechnung wurde erfolgreich gelöscht.")
    except mysql.connector.Error as err:
        print(f"Fehler beim löschen der Berechnung: {err}")

if __name__ == "__main__":
    main()
Sirius3
User
Beiträge: 17844
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein Problem kann ich nicht nachvollziehen. Kannst Du einen Beispielablauf posten, der das Problem zeigt? Also alle Ausgaben und Eingaben.

Zum Programm an sich: `gebühr_berechnen` sollte bei einem Fehler eine Exception werfen. Es ist komisch, dass `display_payment_options` und der Input dazu an zwei Stellen erfolgt, eine Fehlerquelle, wenn sich eins von beiden ändert. Bei einer Fehleingabe sollte dann aber nicht der Betrag abgefragt werden, sondern gleich eine Meldung ausgegeben werden. Nach der Ausgabe von `geben Sie eine gültige Zahlungsoption ein` landet man aber gleich wieder im Hauptmenü.
In den weiteren Funktionen kommen cursor und connection aus dem Nichts. Man darf keine globalen Variablen verwenden. Zudem sind cursor etwas kurzlebiges und sollten nicht in mehreren Funktionen für verschiedene Sachen benutzt werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13268
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@marco2810: Anmerkungen zum Quelltext:

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht. Also die `main()`-Funktion mit „Hauptprogramm“ oder die Funktion `gebühren_berechnen()` mit „Funktion zur Berechnung der PayPal-Gebühren“ zu kommentieren hilft niemandem weiter. Das eine Funktion eine Funktion ist, sollte auch weder Kommentiert noch dokumentiert werden.

`gebührenrate` ist eine Konstante. Statt Kommentare zu schreiben was die Werte im Tupel bedeuten und was die Arten 1 bis 4 bedeuten, wäre es besser das in Code auszudrücken. Beispielsweise über Konstanten für Zahlungsart und Attributnamen statt Positionen im Tupel. Hier würde sich ein Aufzählungstyp (`enum`-Modul) anbieten. Die Berechnung der Gebühr wäre dann recht ”natürlich” eine Methode auf der Zahlungsart.

Auch bei Ergebnissen von Datenbankabfragen sollte man möglichst keine magischen Indexzahlen verwenden, sondern die Wert an sprechende Namen binden.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
from contextlib import closing
from enum import Enum, unique

import mysql.connector


@unique
class Zahlungsart(Enum):
    WAREN_DIENSTLEISTUNGEN = (1, 0.0249, 0.35)
    FREUNDE = (2, 0, 0)
    SPENDEN_SAMMELN = (3, 0.0249, 0.35)
    MIKROZAHLUNG = (4, 0.0499, 0.09)  # Beträge bis 5€

    def __init__(self, id_, prozentsatz, fixe_gebuehr):
        self.id = id_
        self.prozentsatz = prozentsatz
        self.fixe_gebuehr = fixe_gebuehr

    def gebuehr_berechnen(self, betrag):
        gebuehr = betrag * self.prozentsatz + self.fixe_gebuehr
        return round(gebuehr, 2), round(betrag - gebuehr, 2)


ZAHLUNGSART_ID_ZU_ZAHLUNGSART = {
    zahlungsart.id: zahlungsart for zahlungsart in Zahlungsart
}


def save_transaction(connection, zahlungsart, betrag):
    try:
        with closing(connection.cursor()) as cursor:
            cursor.execute(
                "INSERT INTO transaction (zahlungsart, betrag) VALUES (%s, %s)",
                [zahlungsart.id, betrag],
            )
            connection.commit()
        print("Berechnung erfolgreich gespeichert.")
    except mysql.connector.Error as error:
        print(f"Fehler beim Speichern der Berechnung: {error}")


def retrieve_transactions(connection):
    try:
        with closing(connection.cursor()) as cursor:
            cursor.execute("SELECT * FROM transaction")
            print("Gespeicherte Berechnungen:")
            for id_, zahlungsart_id, betrag in cursor.fetchall():
                print("ID:", id_)
                print(
                    "Art der Zahlung:",
                    ZAHLUNGSART_ID_ZU_ZAHLUNGSART[zahlungsart_id].name,
                )
                print("Betrag:", betrag)
                print("--------------------------")
    except mysql.connector.Error as error:
        print(f"Fehler beim Abrufen der Berechnungen: {error}")


def delete_transaction(connection, transaction_id):
    try:
        with closing(connection.cursor()) as cursor:
            cursor.execute(
                "DELETE FROM transaction WHERE id = %s", [transaction_id]
            )
            connection.commit()
        print("Gespeicherte Berechnung wurde erfolgreich gelöscht.")
    except mysql.connector.Error as error:
        print(f"Fehler beim löschen der Berechnung: {error}")


def main():
    with closing(mysql.connector.connect(...)) as connection:
        print("Willkommen beim PayPal-Gebührenrechner!")
        while True:
            print("\nMenü:")
            print("1. Gebühr berechnen")
            print("2. Gespeicherte Berechnungen anzeigen")
            print("3. Gespeicherte Berechnungen löschen")
            print("4. Programm beenden")
            menuewahl = input(
                "Bitte wählen Sie die gewünschte Funktion durch eingabe von"
                " 1, 2, 3 oder 4: "
            ).strip()

            if menuewahl == "1":
                print("Zahlungstypen:")
                print("1. Waren/Dienstleistungen")
                print("2. Freunde")
                print("3. Spenden sammeln")
                print("4. Mikrozahlung")
                while True:
                    zahlungsart_wahl = input(
                        "Bitte wählen Sie die Art der Zahlung durch Eingabe von"
                        " 1, 2, 3 oder 4: "
                    )
                    if zahlungsart_wahl in ["1", "2", "3", "4"]:
                        zahlungsart = ZAHLUNGSART_ID_ZU_ZAHLUNGSART[
                            int(zahlungsart_wahl)
                        ]
                        break

                    print("Ungültige Zahlungsart.")
                #
                # TODO Gegen Falscheingaben absichern.  Also Eingaben die keine
                #      Zahlen sind und negative Zahlen und wahrscheinlich auch
                #      Null.
                #
                betrag = float(
                    input(
                        "Bitte geben Sie den € Betrag ein im Format zz.xx"
                        " (z bis max. 5 stellen):"
                    )
                )
                gebuehr, gesamt_betrag = zahlungsart.gebuehr_berechnen(betrag)
                save_transaction(connection, zahlungsart, betrag)
                print("PayPal-Gebühr:", gebuehr, "€")
                print("Betrag nach Abzug der Gebühr:", gesamt_betrag, "€")

            elif menuewahl == "2":
                retrieve_transactions(connection)

            elif menuewahl == "3":
                transaction_id = input(
                    "Bitte gibt die ID der Berechnung ein, die du löschen"
                    " möchtest: "
                )
                delete_transaction(connection, transaction_id)

            elif menuewahl == "4":
                print("Programm wird beendet.")
                break

            else:
                print("Ungültige Eingabe")


if __name__ == "__main__":
    main()
Bei der Eingabe des Betrags ist es sehr leicht möglich das Programm mit einer Ausnahme abbrechen zu lassen.

Bei der Datenbankanbindung würde ich SQLAlchemy in Betracht ziehen. Dann muss man kein SQL als Zeichenketten zusammenbasteln, und ist auch unabhängig vom DBMS. Bei diesem Programm würde beispielsweise auch SQLite als DB Sinn machen, das verwendet aber in SQL andere Platzhalter als die MySQL-Anbindung. Mit SQLAlchemy wäre man unabhängig von solchen Unterschieden.
Please call it what it is: copyright infringement, not piracy. Piracy takes place in international waters, and involves one or more of theft, murder, rape and kidnapping. Making an unauthorized copy of a piece of software is not piracy, it is an infringement of a government-granted monopoly.
Antworten