Une condition qui renvoie sur une ligne de code

Fermé
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 - Modifié le 26 janv. 2022 à 12:33
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 - 28 janv. 2022 à 13:36
Bonjour.

Je suis débutant en Python, en train de me faire la main sur un petit programme de facturation. Et naturellement, j'ai un problème.

En simplifiant là où il se situe, dans une ligne de facturation, j'ai pour un produit :

ref
(référence),
puht
(prix unitaire hors taxes),
con
(conditionnement),
qte
(quantité) et
ptht
(prix total hors taxes).

Donc, à la base :

ref = str(input('Référence :'))
con = int(input('Conditionnement :'))
puht = float(input('Prix unitaire HT :'))
qte = float(input('Quantité :'))
ptht = puht * qte


Mais je dois tenir compte du conditionnement : la quantité saisie doit être un multiple.

Ce que j'essaie :

if qte % con != 0:
    print('La quantité doit être un multiple du conditionnement')
    # ??? qte ???
else:
    # ??? ptht ???


Si le reste de la division est égal à zéro, on passe au calcul du
ptht
, mais si il est différent, il faut saisir à nouveau la
qte
. Là je bloque, je ne connais pas l'instruction qui permet de remonter sur une ligne.

Merci.
A voir également:

15 réponses

urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43
Modifié le 26 janv. 2022 à 12:26
L'instruction GOTO n'existe pas nativement en Python, faut utiliser des combines

Plutôt que de se compliquer la vie je te suggère une structure du type

qte = float(input('Quantité :'))
tant que qte % con != 0
    print('La quantité doit être un multiple du conditionnement')
    qte = float(input('Quantité :'))
ptht = puht * qte


Au lieu du
if
qui ne s'exécute qu'une seule fois, il te faut une boucle
while
car, je suppose que tu ne peux pas anticiper le nombre de mauvaises saisies qu'il y aura...
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
Modifié le 26 janv. 2022 à 12:27
Oui là ça fait le travail comme il faut. Merci...

J'avais pensé à une boucle mais je me demandais si c'était bien conforme de définir deux fois
qte = float(input('Quantité :'))
0
urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43
Modifié le 26 janv. 2022 à 12:27
C'est tout à fait possible, ça va venir écraser l'ancienne valeur.
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
Modifié le 26 janv. 2022 à 12:28
Écraser l'ancienne valeur, ok, mais si il y avait plusieurs entrées à "dédoubler", ça finirait par faire fouillis, non ?

---

Jusque là tout allait bien mais je m'arrache les cheveux sur la suite car je suis limité à un seul produit. Après avoir validé la quantité et calculé le
ptht
, je dois pouvoir "remonter" pour facturer un second (ou plus) article et au final, sommer le
ptht
de chacun dans le
tht
(total hors taxes) avant de passer à la suite de la facture (qui là ne pose pas de soucis). Je suppose qu'il faut aussi utiliser une boucle
while
mais je ne sais pas du tout comment faire ça.

ref = str(input('Référence :'))
con = int(input('Conditionnement :'))
puht = float(input('Prix unitaire HT :'))
qte = float(input('Quantité :'))

while qte % con != 0:
    print('La quantité saisie doit être un multiple du conditionnement.')
    qte = float(input('Quantité :'))

ptht = puht * qte
print('Prix total HT :',round(ptht, 2))

# (??? tht = somme des ptht ???)
0
urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43
Modifié le 26 janv. 2022 à 12:30
Il te suffit de créer une fonction qui englobe le code qui existe déjà et tu pourras l'appeler 2 fois pour les 2 produits différents.

Tu n'auras plus qu'à sommer le résultat des 2 fonctions

En python pour créer une fonction :

def nomFonction(paramètresProduit):
    # ton code
    return ptht # la valeur retournée par la fonction

ptht1 = nomFonction(argumentsProduit1)
ptht2 = nomFonction(argumentsProduit2)

# Il est possible de sauter l'étape au-dessus et de directement 
# additionner nomFonction(...) qui contient la valeur retournée

somme = ptht1 + ptht2


Je te laisse te renseigner sur ce qu'est un paramètre et un argument pour une fonction, tu en auras peut-être besoin si les caractéristiques changent sinon tu pourras laisser vide les parenthèses

Sinon, plutôt que d'utiliser une fonction, tu peux aussi utiliser une boucle
for
englobant tout ton code pour forcer la répétition x fois mais ensuite ça t'oblige à utiliser une liste pour pouvoir différencier les 2
ptht
.
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49 > urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023
Modifié le 26 janv. 2022 à 12:30
Oui j'ai pensé à une fonction mais je débute. J'ai déjà un peu bidouillé pour me faire la main avec celle-ci (qui n'a rien à voir avec le sujet) :

# Calcul de l'hypoténuse
import math

def hypotenuse(l, h):
 return round(math.sqrt(l**2+h**2), 2)

l = float(input('Largeur :'))
h = float(input('Hauteur :'))

print('Hypoténuse :', hypotenuse(l, h))


Seulement, si je vois à peu près comment structurer la fonction adéquate, à mon niveau je suis incapable de l'intégrer dans le code. D'autant plus qu'il risque d'y avoir plus de deux produits.
0
urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43 > Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022
Modifié le 26 janv. 2022 à 12:31
Tu t'en fiches du nombre de produits. Si tes produits sont référencés de la même manière, disons par exemple un nom, un prénom et un poids par exemple. tu peux créer une et une seule fonction que tu appelleras autant de fois que tu veux.

Vu que l'utilisateur rentre manuellement à chaque fois (avec
input
) les valeurs, et qu'elles n'existent pas déjà dans des variables de ton code, tu n'as même pas besoin de paramètre/argument.

Là, ça revient quasiment juste à mettre tout ton code dans une fonction, quasi rien d'autre à faire mais renseignes-toi bien sûr ce que c'est une fonction et toute la terminologie qui va avec.

Il suffit de stocker le résultat (
return
) dans une variable différente à chaque fois pour ne pas "écraser". et il est aussi possible d'appeler une fonction avec une boucle for :
0
urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43
Modifié le 26 janv. 2022 à 12:32
Méthode non-conseillée avec for et liste, sachant qu'il y a d'autres façon d'écrire la même chose
# déclaration de la liste pour différencier les 2 valeurs 
# et ne pas écraser quand on passe au deuxième produit
ptht = []

for x in range(2):
    # ton code ici
    ptht[x] = puht * qte # on accède au "x-ième" élément de la liste
    print('Prix total HT :',round(ptht[x], 2))

tht = ptht[0] + ptht[1]
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 26 janv. 2022 à 12:32
Bonsoir,

Peut-être en mettant tout ça dans une boucle
while(True):
et en faisant un
break
pour sortir si
ref == 'quitter'
.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
24 janv. 2022 à 18:24
Phil_1857, même réponse : je suis débutant et c'est pour le moment compliqué...
0
urilou777 Messages postés 319 Date d'inscription samedi 22 janvier 2022 Statut Membre Dernière intervention 12 janvier 2023 43
Modifié le 24 janv. 2022 à 19:43
je te conseille le site http://www.france-ioi.org/

il y a une approche pas à pas, niveau par niveau

les énoncés sont donnée de façon rigolote avec des "extraterrestres" et compagnie

tu peux progresser vite la dessus, les leçons sont bien expliquées
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
Modifié le 26 janv. 2022 à 12:34
De retour...

Alors j'ai créé la fonction qui calcule le prix total hors taxes (donc, somme de chaque ligne) :

def ptht(puht, rab, qte):
    return round(puht - rab) * qte, 2)


Mais je ne sais ni où la placer ni comment l'utiliser...
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803
Modifié le 26 janv. 2022 à 14:15
Bonjour à tous,

@Tous

J'ai corrigé vos messages pour utiliser la coloration syntaxique. Pour l'utiliser cliquez à côté du triangle à côté du bouton code. Plus de détails dans ce tutoriel ou en modifiant l'un de vos anciens messages.

@Nerva, message #12

qu'appelles-tu
rab
? Note que dans ta fonction il manque une parenthèse ouvrante.

def saisie():
    ref = str(input('Référence :'))
    con = int(input('Conditionnement :'))
    puht = float(input('Prix unitaire HT :'))
    qte = float(input('Quantité :'))

    while qte % con != 0:
        print('La quantité saisie doit être un multiple du conditionnement.')
        qte = float(input('Quantité :'))

    rab = float(input("Rab :"))
    return (ref, con, puht, qte, rab)

def ptht(puht, rab, qte):
    return round((puht - rab) * qte, 2)

for _ in range(5): # Saisir 5 produits
    (ref, con, puht, qte, rab) = saisie()
    x = ptht(puht, rab, qte)
    print('Prix total HT :', x)


Note qu'il faudrait sans doute contrôler dans saisie avec des boucles while que les valeurs saisies sont des entiers positifs. Note aussi que convertir une saisie en entier peut échouer si la chaîne n'est pas un texte correspondant à une valeur entière. Dans ce cas python lèvera une exception, que tu peux rattraper (par exemple, en vue de re-demander une valeur correcte.

def input_cast(label = "", cast = lambda x: x):
    while True:
        try:
            return cast(input(label))
        except ValueError:
            pass

i = input_cast("Saisir un entier", int)
x = input_cast("Saisir un réel", float)



Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
26 janv. 2022 à 14:23
Là déjà merci, je commence à voir comment tout cela se structure...

J'ai corrigé la parenthèse et j'ajouterai dorénavant le formatage du code en python.

Le rabais est une réduction accordée pour un produit selon son état. Par exemple, un lot de flacons où l'étiquette serait collée de travers est proposée avec un rabais de 10 %.

Dans le but de simplifier, j'ai compliqué tout. Il y a le taux de rabais en % (t_rab), celui qu'on saisit dans la facture, et le montant du rabais (rab), qui est calculé.

rab = puht*(t_rab/100)
ptht = (puht-rab)*qte


J'ai modifié le code mais j'ai fait une erreur quelque part puisqu'il y a un message après la saisie de t_rab :

def saisie():
    ref = str(input('Référence :'))
    con = int(input('Conditionnement :'))
    puht = float(input('Prix unitaire HT :'))
    qte = float(input('Quantité :'))

    while qte % con != 0:
        print('La quantité saisie doit être un multiple du conditionnement.')
        qte = float(input('Quantité :'))

    t_rab = float(input('Rabais (%) :'))
    return (ref, con, puht, qte, t_rab)

def rab(puht, t_rab):
    return round(puht*(t_rab/100))

def ptht(puht, rab, qte):
    return round((puht - rab) * qte, 2)

for _ in range(5): # Saisir 5 produits
    (ref, con, puht, qte, t_rab) = saisie()
    x = ptht(puht, rab, qte)
    print('Prix total HT :', x)


En ce qui concerne le contrôle de la saisie, je verrai par la suite comment implanter des "gardes-fous" (je ne pense pas que ça soit le plus compliqué). Par contre, avec un un range de 5, ça oblige à saisir 5 produits alors que le nombre sera toujours variable selon la liste des produits disponibles et la commande qui est faite.
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803
Modifié le 26 janv. 2022 à 15:02
Bonjour,

C'est parce que par endroit dans ton code tu confonds la fonction
rab
et la valeur
t_rab
. Du coup tu te retrouves à impliquer une fonction dans un calcul numérique, d'où l'erreur. Voici à quoi pourrait ressembler ton programme une fois corrigé.

def saisie():
    ref = str(input('Référence :'))
    con = int(input('Conditionnement :'))
    puht = float(input('Prix unitaire HT :'))
    qte = float(input('Quantité :'))

    while qte % con != 0:
        print('La quantité saisie doit être un multiple du conditionnement.')
        qte = float(input('Quantité :'))

    t_rab = float(input('Rabais (%) :'))
    return (ref, con, puht, qte, t_rab)

def rab(puht, t_rab):
    return round(puht * (t_rab / 100))

def ptht(puht, rab, qte):
    return round((puht - rab) * qte, 2)

for _ in range(5): # Saisir 5 produits
    (ref, con, puht, qte, t_rab) = saisie()
    rabais = rab(puht, t_rab)
    x = ptht(puht, rabais, qte)
    print('Prix total HT :', x)    


Personnellement, je te conseille pour éviter toute confusion de mettre un verbe dans tes noms de fonctions. Si on fait le parallèle avec la grammaire française, vois un peu les variables comme des noms et des adjectifs, et vois les fonctions comme des verbes. De la même manière, je te recommande d'avoir des noms de variables parlants (les abréviations rendent le code dur à relire quelques mois plus tard :p).

Concernant le nombre de produit, ici on a effectivement mis 5 en dur. Tout dépend de ce que tu veux faire. Si tu as une liste de produit, tu peux remplacer 5 par la longueur de ce catalogue. Si tu n'as pas de catalogue et que le but de ton programme est de le peupler, tu peux remplacer la boucle
for
par un
while True ...
que tu interrompras quand l'utilisateur le décidera (quitte à poser une question supplémentaire du genre "Saisir un autre produit ? (o/n)").

Une fois remis en forme, ton code pourrait par exemple ressembler à ceci :

def input_cast(label = "", cast = lambda x: x):
    while True:
        try:
            return cast(input(label))
        except ValueError:
            pass

def prompt_product():
    reference = input('Référence :')
    conditionnement = input_cast('Conditionnement :', int)
    puht = input_cast('Prix unitaire HT :', float)
    quantite = input_cast('Quantité :', float)

    while quantite % conditionnement != 0:
        print('La quantité saisie doit être un multiple du conditionnement.')
        qte = input('Quantité :', float)

    taux_rabais = input_cast('Rabais (%) :', float)
    return (reference, conditionnement, puht, quantite, taux_rabais)

def compute_rabais(puht, taux_rabais):
    return round(puht * (taux_rabais / 100))

def compute_ptht(puht, rabais, quantite):
    return round((puht - rabais) * quantite, 2)

while True:
    (reference, conditionnement, puht, quantite, taux_rabais) = prompt_product()
    rabais = compute_rabais(puht, taux_rabais)
    ptht = compute_ptht(puht, rabais, quantite)
    print('Prix total HT :', ptht)
    continuer = input("Saisie terminée (o/n)")
    if continuer == "o":
        break


Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
26 janv. 2022 à 15:28
Là ça avance bien. Maintenant la suite sera de trouver la fonction qui permette de totaliser les ptht de chaque ligne dans le tht.

J'ai compris que le imput_cast interdit les saisies non conformes. Par contre, il semble y avoir un conflit avec while quantite % conditionnement != 0: puisque ça plante au niveau de la quantité si elle n'est pas un multiple du conditionnement.

Merci encore...
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803
Modifié le 26 janv. 2022 à 16:22
Bonjour,

Pour vérifier si les valeurs saisies vérifient une certaine propriété (par exemple, s'agit-il d'une valeur positive), tu peux compléter
input_cast
en lui passant en paramètre optionnel une fonction (que je nomme ci-dessous
check_positive
) qui va vérifier si cette propriété est vérifié.

Concernant le calcul de la somme des ptht, il suffit de créer une variable que tu vas incrémenter à chaque tour de boucle avec le ptht calculé.

def input_cast(label = "", cast = lambda x: x, check = lambda: True):
    while True:
        try:
            ret = cast(input(label))
            if check(ret):
                return ret
            else:
                print("Valeur invalide!")
        except ValueError:
            pass

def check_positive(x):
    return x > 0

def prompt_product():
    reference = input('Référence :')
    conditionnement = input_cast('Conditionnement :', int, check_positive)
    puht = input_cast('Prix unitaire HT :', float, check_positive)
    quantite = input_cast('Quantité :', float, check_positive)

    while quantite % conditionnement != 0:
        print('La quantité saisie doit être un multiple du conditionnement.')
        qte = input('Quantité :', float, check_positive)

    taux_rabais = input_cast('Rabais (%) :', float, check_positive)
    return (reference, conditionnement, puht, quantite, taux_rabais)

def compute_rab(puht, taux_rabais):
    return round(puht * (taux_rabais / 100))

def compute_ptht(puht, rabais, quantite):
    return round((puht - rabais) * quantite, 2)

ptht_total = 0
while True:
    (reference, conditionnement, puht, quantite, taux_rabais) = prompt_product()
    rabais = compute_rab(puht, taux_rabais)
    ptht = compute_ptht(puht, rabais, quantite)
    print('Prix total HT :', ptht)
    ptht_total += ptht
    continuer = input("Saisie terminée (o/n)")
    if continuer == "o":
        break
print("Total des PTHT", ptht_total)


Ensuite si tu veux aller plus loin, il faudrait probablement créer une classe qui stocke chaque produit (
class Product
) et dont la définition dépend de ce qui caractérise un Produit. De la même manière, tu pourrais avoir un objet
Ordering
qui concerne un
Product
, une quantité, et un calcul de rabais. Ensuite, tu peux imaginer demander la saisie de tes produits dans un premier temps, puis celles de tes commandes dans un second temps.

Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
26 janv. 2022 à 18:32
Eh bien toujours merci... C'est donc avec le += qu'on cumule les montants et préalablement en déclarant le total à zéro. Là j'ai juste enlevé le check_positive au rabais (dans la réalité, le nombre de produits proposés au rabais est très minoritaire).

Je vais étudier tout ça avec attention (surtout les deux premières fonctions) et je passerai à la suite un peu plus tard. Dans mon idée je voulais faire les choses en trois temps : la partie de base, fonctions, calculs ; intégrer les produits dans une liste pour ne plus avoir à taper que la référence (puisque dans la réalité, il y a d'autres colonnes) ; et enfin, les intégrer dans une base de données (domaine où je suis nettement plus à l'aise).

Merci.
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803 > Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022
27 janv. 2022 à 12:43
C'est donc avec le += qu'on cumule les montants et préalablement en déclarant le total à zéro.

Effectivement tu peux utiliser
x += n
qui est équivalent à
x = x + n
.
  • De même, les opérateurs
    -=
    ,
    *=
    ,
    /=
    ,
    %=
    ,
    |=
    ,
    &=
    correspondent aux opérateurs
    -
    (soustraction),
    *
    (multiplication),
    /
    (division),
    %=
    (modulo),
    |=
    (ou logique),
    &=
    (et logique).
  • Certains langages, comme le Java et le C++ mettent aussi à disposition
    x++
    et
    x--
    , qui signifient respectivement
    x += 1
    et
    x -= 1
    mais ils n'existent pas en python.


Dans mon idée je voulais faire les choses en trois temps : la partie de base, fonctions, calculs ; intégrer les produits dans une liste pour ne plus avoir à taper que la référence (puisque dans la réalité, il y a d'autres colonnes) ;

Note que l'opérateur
+
permet de concaténer deux listes (tu as donc ici aussi un opérateur
+=
), et sinon tu peux utiliser la méthode
append
pour ajouter un élément en fin de liste. Au sens base de données, cette liste correspond plus ou moins au contenu d'une table.

et enfin, les intégrer dans une base de données (domaine où je suis nettement plus à l'aise).

Si tu es plus à l'aise avec les bases de données, dis-toi que les objets python qu'il faudrait déclarer correspondent plus ou moins aux tables de ta base de données. Chaque instance d'un objet correspond à un enregistrement au sens base de donnée.

Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
27 janv. 2022 à 13:58
Alors voilà où j'en suis...

1) J'ai renommé les entrées à ma convenance, séparant produit (prefixe pro_) et facturation (préfixe fac_) afin de m'y retrouver plus facilement pour la suite.

2) J'ai rajouté deux entrées pour le produit : la désignation et le code TVA (1, taux réduit ; 2, taux normal). Maintenant que je connais la façon de faire (enfin j'espère !), je vais modifier l'ensemble pour séparer les produits selon leur code TVA.

3) J'ai ajouté tout ce qu'il y a après le Total Hors Taxes.

4) Enfin, là où j'ai encore un problème, c'est dans l'affichage final (voir code). S'affiche sur une ligne tous les éléments de la facture. Problème : si je facture au moins 2 produits, seul le dernier s'affiche (néanmoins, les résultats des calculs ne sont pas affectés).

def input_cast(label = "", cast = lambda x: x, check = lambda: True):
    while True:
        try:
            ret = cast(input(label))
            if check(ret):
                return ret
            else:
                print('Valeur invalide !')
        except ValueError:
            pass

def check_positive(x):
    return x > 0

def prompt_produits():
    pro_ref = input('Référence : ')
    pro_des = input('Désignation : ')
    pro_con = input_cast('Conditionnement : ', int, check_positive)
    pro_puht = input_cast('Prix unitaire HT : ', float, check_positive)
    pro_tva_c = input_cast('Code TVA : ', int, check_positive)
    fac_qte = input_cast('Quantité : ', float, check_positive)

    while fac_qte % pro_con != 0:
        print('La quantité saisie doit être un multiple de', pro_con)
        fac_qte = input_cast('Quantité : ', float, check_positive)

    fac_rab_t = float(input('Rabais (%) : '))
    return (pro_ref, pro_des, pro_con, pro_puht, pro_tva_c, fac_qte, fac_rab_t)

def calcul_rab(pro_puht, fac_rab_t):
    return round(pro_puht * (fac_rab_t / 100), 2)

def calcul_ptht(pro_puht, fac_rab, fac_qte):
    return round((pro_puht - fac_rab) * fac_qte, 2)

fac_tht = 0

while True:
    (pro_ref, pro_des, pro_con, pro_puht, pro_tva_c, fac_qte, fac_rab_t) = prompt_produits()
    fac_rab = calcul_rab(pro_puht, fac_rab_t)
    fac_ptht = calcul_ptht(pro_puht, fac_rab, fac_qte)
    print('Prix total HT : ', fac_ptht)
    fac_tht += fac_ptht
    continuer = input('Saisie terminée (o/n)')
    if continuer == 'o':
        break
print('Total HT : ', fac_tht)

fac_rem_t = float(input('Remise (%) : '))
fac_esc_t = float(input('Escompte au règlement (%) : '))
fac_fdp = float(input('Frais de port : '))
fac_fde = float(input('Frais d\'emballage : '))

fac_rem = round(fac_tht * (fac_rem_t / 100), 2)
fac_mnc = round(fac_tht - fac_rem, 2)
fac_esc = round(fac_mnc * (fac_esc_t / 100), 2)
fac_mnht = round(fac_mnc - fac_esc, 2)
fac_tnht = round(fac_mnht + fac_fdp + fac_fde, 2)
fac_tva = round(fac_tnht * 0.2, 2)
fac_tttc = round(fac_tnht + fac_tva, 2)

print('------------------------------------------------------------------------------------------------------')
print(' Réf      | Désignation                |   Cond. |     PU HT | TVA |   Rabais |       Qte |     PT HT ')
print('------------------------------------------------------------------------------------------------------')
print (f' {pro_ref:11}{pro_des:27}{pro_con:>9}{pro_puht:>12.2f}{pro_tva_c:>6}{fac_rab:>11.2f}{fac_qte:>12.2f}{fac_ptht:>12.2f}')
print('\n------------------------------------------------------------------------------------------------------\n')
print(f'Total HT :\t\t\t{fac_tht:>12.2f}')
print('......................................................................................................')
print(f'Remise :\t\t\t{fac_rem:>12.2f}')
print(f'Montant net commercial :\t{fac_mnc:>12.2f}')
print('......................................................................................................')
print(f'Escompte au règlement :\t\t{fac_esc:>12.2f}')
print(f'Montant net HT :\t\t{fac_mnht:>12.2f}')
print('......................................................................................................')
print(f'Frais de port :\t\t\t{fac_fdp:>12.2f}')
print(f'Frais d\'emballage :\t\t{fac_fde:>12.2f}')
print(f'Total net HT :\t\t\t{fac_tnht:>12.2f}')
print('......................................................................................................')
print(f'TVA :\t\t\t\t{fac_tva:>12.2f}')
print('......................................................................................................')
print(f'Total TTC :\t\t\t{fac_tttc:>12.2f}')
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803
27 janv. 2022 à 16:29
Bonjour,

Je pense qu'il est temps de commencer à faire des objets si tu commences à t'y perdre. Voici ce que je te propose :

def input_cast(label = "", cast = lambda x: x, check = lambda: True):
    while True:
        try:
            ret = cast(input(label))
            if check(ret):
                return ret
            else:
                print('Valeur invalide !')
        except ValueError:
            pass

def check_positive(x):
    return x > 0

class Product:
    def __init__(self, ref, des, con, puht, tva_c):
        self.ref = ref
        self.des = des
        self.con = con
        self.puht = puht
        self.tva_c = tva_c

class OrderedProduct(Product):
    def __init__(self, ref, des, con, puht, tva_c, qte, rab_t):
        super().__init__(ref, des, con, puht, tva_c)
        self.qte = qte
        self.rab_t = rab_t
        self.rab = self.calcul_rab()
        self.ptht = self.calcul_ptht()
        
    def calcul_rab(self):
        return round(self.puht * (self.rab_t / 100), 2)
    
    def calcul_ptht(self):
        return round((self.puht - self.rab) * self.qte, 2)

def prompt_ordered_product():
    ref = input('Référence : ')
    des = input('Désignation : ')
    con = input_cast('Conditionnement : ', int, check_positive)
    puht = input_cast('Prix unitaire HT : ', float, check_positive)
    tva_c = input_cast('Code TVA : ', int, check_positive)
    qte = input_cast('Quantité : ', float, check_positive)

    while qte % con != 0:
        print('La quantité saisie doit être un multiple de', con)
        qte = input_cast('Quantité : ', float, check_positive)

    rab_t = float(input('Rabais (%) : '))
    return OrderedProduct(ref, des, con, puht, tva_c, qte, rab_t)

class Billing:
    def __init__(self, tht, rem_t, esc_t, fdp, fde):
        self.tht = tht
        self.rem_t = rem_t
        self.esc_t = esc_t
        self.fdp = fdp
        self.fde = fde
        self.rem = round(self.tht * (self.rem_t / 100), 2)
        self.mnc = round(self.tht - self.rem, 2)
        self.esc = round(self.mnc * (esc_t / 100), 2)
        self.mnht = round(self.mnc - self.esc, 2)
        self.tnht = round(self.mnht + self.fdp + self.fde, 2)
        self.tva = round(self.tnht * 0.2, 2)
        self.tttc = round(self.tnht + self.tva, 2)
        
def prompt_billing(tht):
    rem_t = input_cast('Remise (%) : ', float, check_positive)
    esc_t = input_cast('Escompte au règlement (%) : ', float, check_positive)
    fdp = input_cast('Frais de port : ', float, check_positive)
    fde = input_cast('Frais d\'emballage : ', float, check_positive)
    return Billing(tht, rem_t, esc_t, fdp, fde)

class Bill:
    def __init__(self, ordered_products, billing):
        self.ordered_products = ordered_products
        self.billing = billing
    def __str__(self):
        s = f"""Total HT : {self.billing.tht}
------------------------------------------------------------------------------------------------------
 Réf      | Désignation                |   Cond. |     PU HT | TVA |   Rabais |       Qte |     PT HT
------------------------------------------------------------------------------------------------------"""
        
        for pro in self.ordered_products:
            s += f' {pro.ref:11}{pro.des:27}{pro.con:>9}{pro.puht:>12.2f}{pro.tva_c:>6}{pro.rab:>11.2f}{pro.qte:>12.2f}{pro.ptht:>12.2f}\n'

        s += f"""------------------------------------------------------------------------------------------------------
        
Total HT :\t\t\t{self.billing.tht:>12.2f}
.....................................................................................................
Remise :\t\t\t{self.billing.rem:>12.2f}
Montant net commercial :\t{self.billing.mnc:>12.2f}
......................................................................................................
Escompte au règlement :\t\t{self.billing.esc:>12.2f}
Montant net HT :\t\t{self.billing.mnht:>12.2f}
......................................................................................................
Frais de port :\t\t\t{self.billing.fdp:>12.2f}
Frais d\'emballage :\t\t{self.billing.fde:>12.2f}
Total net HT :\t\t\t{self.billing.tnht:>12.2f}
......................................................................................................
TVA :\t\t\t\t{self.billing.tva:>12.2f}
......................................................................................................
Total TTC :\t\t\t{self.billing.tttc:>12.2f}"""
        return s
    
def main():
    tht = 0
    ordered_products = list()
    while True:
        pro = prompt_ordered_product()
        ordered_products.append(pro)
        print('Prix total HT : ', pro.ptht)
        tht += pro.ptht
        continuer = input('Saisie terminée (o/n)')
        if continuer == 'o':
            break
    billing = prompt_billing(tht)
    bill = Bill(ordered_products, billing)
    print(bill)
    
main()


Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
27 janv. 2022 à 17:45
C'est avec les objets que je vais commencer à m'y perdre ! Ça devient vraiment complexe et il me faut le temps de digérer...
0
mamiemando Messages postés 33385 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 novembre 2024 7 803
Modifié le 27 janv. 2022 à 18:04
Ah ok, en fait c'est juste que les objets font naturellement le travail de "regroupement" que tu faisais avec des préfixes
pro_
et
fac_
. Tu peux voir un objet comme une sorte de tuple typé, dont chaque élément est accédé par un nom dédié.

Voici un exemple simple d'objet :

class Personne:
    def __init__(self, prenom, nom):
        self.prenom = prenom
        self.nom = nom
    def dit(self, message):
        print(f"{self.prenom} {self.nom} dit {message}")

p = Personne("Albert", "Einstein") # p est initialié conformément à Personne.__init__
print(p.nom)
print(p.prenom)
p.dit("bonjour") # Albert Einstein dit bonjour
  • Personne
    correspond à une classe (ou objet) ;
  • p
    correspond à une instance de
    Personne
    .
  • nom
    et
    prenom
    sont des attributs de
    Personne
    .


Quand tu déclares un objet, l'instance à laquelle s'applique une méthode est noté
self
désigne l'instance courante (e.g.
p
).

Si tu as compris ça tu as compris l'essentiel et le code que je t'ai partagé devrait être assez clair.

L'avantage des objets (outre le fait qu'ils rendent le code mieux organisé et plus clair), c'est qu'on peut réutiliser des objets pour en définir d'autres (soit en tant qu'attribut, comme j'ai fait pour
Bill
, soit par héritage, comme j'ai fait pour
OrderedProduct
).

Mais bref, si tu ne te sens pas d'utiliser des objets, continue avec ton code :-)

Bonne chance
0
Nerva Messages postés 318 Date d'inscription mardi 9 mars 2004 Statut Membre Dernière intervention 20 décembre 2022 49
Modifié le 28 janv. 2022 à 13:39
Même lorsque j'aurai assimilé tout ça, dans l'état actuel, ça me semble très confus. Les préfixes que j'avais mis sont une habitude qui me vient des bases de données afin de bien séparer les items. Par exemple, pour le prix d'un produit, je choisis :

- PRO_PUHT dans la table T_PRODUITS.
- FAC_PUHT (et FAC_QTE, entre autre) dans la table T_VENTES_SUB

Données ensuite envoyées dans la requête pour les calculs.

Bref, comme je songe intégrer tout ça dans une base de données (bien que je n'en sois pas encore là), j'ai pris les devants en renommant les items à ma manière habituelle...
0