Code python contient des erreurs , méthode non correct

Résolu/Fermé
mohafor - Modifié le 24 févr. 2023 à 03:08
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 - 24 févr. 2023 à 03:19

Bonjour,
J'ai développé ce code python, mais le résultat n'est celui que j’attends :

from abc import ABC, abstractmethod
 
 
class InvoiceCalc:
    """
    Calcul des montants à facturer
    """
    __taux_tva = 0.21
    __instance = None
 
    @classmethod
    def singleton(taux_tva):
        if not InvoiceCalc.__instance:
            InvoiceCalc.__instance = InvoiceCalc()
            InvoiceCalc.__instance.__taux_tva = InvoiceCalc(taux_tva)
 
    def __init__(self):
     pass
 
    def compute_perform(self, price, dur):
        """ calcule le montant à facturer (htva, tva, ttc)
            pour cet employé "emp" et
            pour cette durée de prestation  "dur"
            avec le tarif horaire "price" = emp.price
        """
        montant = dur * price
        return self.compute_expense(montant)
 
    def compute_expense(self, exp):
        """ calcule et retourne le montant à facturer (htva, tva, ttc)
            pour cette dépense "exp"
        """
        montant = exp
        tva = montant * self.__taux_tva
        montant_ttc = montant + tva
        return ( montant, tva, montant_ttc )
 
class Project:
    """
    Gestion des enregistrements du temps d'un employé
    sur un projet pour un client.
    A ne pas modifier !
    """
    def __init__(self, project="", client=""):
        self.__client = ""
        self.__project = project
        self.__perform_l = []
        self.__expense_l = []
        self.__client = client
 
    def perform(self, emp, det, dur):
        if isinstance(emp, Employee):
            self.__perform_l.append({
                "name":     emp.name,
                "detail":   det,
                "duration": float(dur),
                "price":    emp.price
            })
 
    def expense(self, emp, subject, amount):
        self.__expense_l.append({
            "name":   emp.name,
            "detail": subject,
            "amount": float(amount)
        })
 
    def __iter__(self):
        self.index = 0
        self.inv_calc = InvoiceCalc()
        return self
 
    def __next__(self):
        if self.index >= len(self.__expense_l):
            raise StopIteration
        data = self.__expense_l[self.index]
        self.index += 1
        amount = data['amount']
        htva, tva, ttc = self.inv_calc.compute_expense(amount)
        return f'{data["detail"]},{htva},{tva},{ttc}'
        #return data
 
    def __str__(self):
        # templates
        header_s = \
    """
    Client  : {1}
    Projet  : {2}
 
    """
        header_perform_s = \
    """
    Détail des prestations (h, €)
    """
        header_expense_s = \
    """
    Détail des dépenses (€)
    """
        perform_str = "{2:8} {0:26} {5:>6.2f}€/h {1:>6.2f}h {4:>6.0f}€\n"
        expense_str = "{2:8} {0:26}                   {4:>6.0f}€\n"
        title_str = "{2:^8} {0:^26} {5:^8} {1:^9} {4:^7}\n"
        t_p = 0  # total prestation
        t_i = 0  # total facturation
        t_e = 0  # total expense
        final_fs = ""
 
        # header
        final_fs += header_s.format("", self.__client, self.__project)
 
        # body "perform"
        final_fs += header_perform_s
        final_fs += title_str.format("TASK", "DUR", "PERSON", "DEPT", "INV", "PRICE")
        for data in self.__perform_l:
            inv_c = InvoiceCalc()
            to_invoice_tuple = inv_c.compute_perform(data["price"], data["duration"])
            final_fs += perform_str.format(
                data["detail"],
                data["duration"],
                data["name"],
                "",
                to_invoice_tuple[0],
                data["price"]
            )
            t_p += data["duration"]
            t_i += to_invoice_tuple[0]
        final_fs += "\n" + perform_str.format("Total perform", t_p, "", "", t_i, 0) + "\n"
 
        # body "expense"
        final_fs += header_expense_s
        final_fs += title_str.format("EXPENSE", "", "PERSON", "DEPT", "INV", "")
        for data in self.__expense_l:
            inv_c = InvoiceCalc()
            to_invoice_tuple = inv_c.compute_expense(data["amount"])
            final_fs += expense_str.format(
                data["detail"],
                0,
                data["name"],
                "",
                to_invoice_tuple[0]
            )
            t_e += to_invoice_tuple[0]
        final_fs += "\n" + expense_str.format("Total expense", 0, "", "", t_e) + "\n"
 
        # footer
        final_fs += "\n" + expense_str.format("Total général", 0, "******", "***********", t_e + t_i) + "\n"
 
        return final_fs
 
 
class Employee(ABC):
    def __init__(self, name):
        self.name = name
 
    @property
    @abstractmethod
    def price(self):
        return self.price
        #pass
 
    @property
    @abstractmethod
    def department(self):
        return self.department
        #pass
 
    @classmethod
    def factory(self, name, function):
        if function == "Geek":
            return Geek(name)
        elif function == "hardware":
            return HardwareGeek(name)
        elif function == "technical manager":
            return TechnicalManager(name)
        elif function == "account manager":
            return AccountManager(name)
        else:
            raise ValueError("Unknown employee type")
        #return EmployeeFake(name)
 
 
class EmployeeFake(Employee):
    department = "circus"
    price = 15
 
 
class EmployeeHardware(Employee):
    department = "hardware"
    project_o = Project("installation de deux PC", "Lehman Brothers Bank")
    emp = "kim"
    det = {"achat matériel MAC", "configuration matériel", "installation chez client"}#"detail"
    dur = 0
    project_o.perform(emp, det, dur)
    detail = det
 
class Geek(EmployeeHardware):
    price = 60
 
 
class HardwareGeek(EmployeeHardware):
    price = 0
 
    def pricing_intel(self):
        self.price = 65
        return self.price
        # pass
 
    def pricing_mac(self):
 
        detail = {"achat matériel MAC", "configuration matériel", "installation chez client"}
        if detail == "achat matériel MAC":
            self.price = 75
        if detail == "configuration matériel":
            self.price = 50
        elif detail == "installation chez client":
            self.price = 50
        else :self.price = 75
 
       
class TechnicalManager(EmployeeHardware):
    price = 90
 
 
class AccountManager(Employee):
    department = "account"
    price = 100
 
 
 
if __name__ == '__main__':
    #
 
    # 1)
    kim = Employee.factory("Kim", "hardware" )  # return HardwareGeek object
    ali = Employee.factory("Ali", "hardware" )  # return HardwareGeek object
    albert = Employee.factory("Albert", "technical manager") # return TechnicalManager object
    sophie = Employee.factory("Sophie", "account manager")   # return AccountManager object
 
    # 2)
    project_o = Project("installation de deux PC", "Lehman Brothers Bank")
 
    # 3)
    project_o.perform(albert, "réunion avec client", 1)
    kim.pricing_intel() # on passe au tarif "PC"
    project_o.perform(kim, "achat matériel PC", 0.5)
    kim.pricing_mac()   # on passe au tarif "MAC"
    project_o.perform(kim, "achat matériel MAC", 1.5)
    project_o.perform(ali, "configuration matériel", 2)
    project_o.perform(ali, "installation chez client", 3)
    project_o.perform(albert, "remise des clés", 0.5)
    project_o.perform(sophie, "convention avec le client", 0.5)
 
    # on ajoute des dépenses
    project_o.expense(kim, "deux PC et accessoires", 1500)
    project_o.expense(kim, "trois MAC et accessoires", 4500)
 
     
    # 4)
    print("CSV")
 
    project_it = iter(project_o)
    while True:
        try:
            # iteration
            csv = next(project_it)
            print(csv)
        except StopIteration:
            # quand tous les enregistrements ont été reçus
            break

Le problème est dans la méthode pricing_mac() (l208) de la classe HardwareGeek : quand je l'appelle cette méthode, je veux que le tarif change, mais ce n'est pas le cas.

Pouvez-vous m'aider s'il vous plaît ?

A voir également:

2 réponses

Bonsoir,

Le code de ta méthode n'a pas de sens, tu définis un set de strings  (pourquoi un set ?), et juste à la suite tu compares ce set à de simple chaines, déjà tu entreras toujours dans le else.

Il manque donc forcément l'initialisation de valeurs dans ta classe, detail devrait être un attribut de classe et non une simple variable, il faudrait décrire ce que doit faire ton code, une classe HardwareGeek dérivée de EmployeeHardware semble quand même pas très logique.

0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
24 févr. 2023 à 03:19

Bonjour,

Pour commencer, ce serait bien de partager un code minimal qui met en évidence le problème. Les seules lignes utiles sont :

class HardwareGeek(EmployeeHardware):
    price = 0
 
    def pricing_intel(self):
        self.price = 65
        return self.price
        # pass
 
    def pricing_mac(self):
        detail = {"achat matériel MAC", "configuration matériel", "installation chez client"}
        if detail == "achat matériel MAC":
            self.price = 75
        if detail == "configuration matériel":
            self.price = 50
        elif detail == "installation chez client":
            self.price = 50
        else:
            self.price = 75

Ensuite je pense que ton problème vient de la manière dont ta classe est déclarée.

Comme l'indique rusti #1, tu compares un ensemble de chaîne avec une chaîne. Tes tests d'égalités sont donc toujours faux et tu es donc systématiquement dans le "else". Ensuite, quel est l'intérêt d'écrire une méthode qui ne dépend d'aucun paramètre. J'ai l'impression que ta méthode devrait dépendre d'un paramètre détail, contrôler si elle est bien dans l'ensemble des détails valides, puis faire le test.

Enfin, la manière dont tu initialises ta classe me paraît suspecte. Je t'invite à écrire un constructeur. Je pense que tu confonds attributs de classe (spécifique à une instance de classe) et variable de classe (commune à toutes les instances de cette classe). Voir cette discussion.

Je ne sais pas si c'est ce que tu veux faire, mais si c'est le cas, ta classe devrait plutôt ressembler à ceci :

class HardwareGeek(EmployeeHardware):
    def __init__(self):
        price = 0
 
    def pricing_intel(self):
        self.price = 65
        return self.price
        
    def pricing_mac(self, detail):
        if detail not in {
           "achat matériel MAC",
           "configuration matériel",
           "installation chez client"
        }:
            raise ValueError(detail)
        if detail == "achat matériel MAC":
            self.price = 75
        if detail == "configuration matériel":
            self.price = 50
        elif detail == "installation chez client":
            self.price = 50
        else:
            self.price = 75

Bonne chance

0