IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Introduction à Python 3 et au framework web Flask par l'exemple


précédentsommairesuivant

11. Exercice d’application : version 3

Image non disponible

Cette nouvelle version introduit deux changements :

  • les données nécessaires au calcul de l'impôt et fournies par l'administration fiscale sont placées dans un fichier jSON [admindata.json] :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
{
    "limites": [9964, 27519, 73779, 156244, 0],
    "coeffR": [0, 0.14, 0.3, 0.41, 0.45],
    "coeffN": [0, 1394.96, 5798, 13913.69, 20163.45],
    "PLAFOND_QF_DEMI_PART": 1551,
    "PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION": 21037,
    "PLAFOND_REVENUS_COUPLE_POUR_REDUCTION": 42074,
    "VALEUR_REDUC_DEMI_PART": 3797,
    "PLAFOND_DECOTE_CELIBATAIRE": 1196,
    "PLAFOND_DECOTE_COUPLE": 1970,
    "PLAFOND_IMPOT_COUPLE_POUR_DECOTE": 2627,
    "PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE": 1595,
    "ABATTEMENT_DIXPOURCENT_MAX": 12502,
    "ABATTEMENT_DIXPOURCENT_MIN": 437
}
  • les résultats du calcul de l'impôt seront eux également placés dans un fichier jSON [résultats.json] :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
[
  {
    "marié": "oui",
    "enfants": 2,
    "salaire": 55555,
    "impôt": 2814,
    "surcôte": 0,
    "décôte": 0,
    "réduction": 0,
    "taux": 0.14
  },
  {
    "marié": "oui",
    "enfants": 2,
    "salaire": 50000,
    "impôt": 1384,
    "surcôte": 0,
    "décôte": 384,
    "réduction": 347,
    "taux": 0.14
  },{
    "marié": "oui",
    "enfants": 3,
    "salaire": 200000,
    "impôt": 42842,
    "surcôte": 17283,
    "décôte": 0,
    "réduction": 0,
    "taux": 0.41
  }
]

11-1. Le script de configuration [config.py]

Le script de configuration sera le suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
def configure():
    import os

    # chemin absolu du dossier de ce script
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # dépendances de l'application
    absolute_dependencies = [
        f"{script_dir}/../shared",
    ]
    # configuration de l'application
    config = {
        # chemin absolu du fichier des contribuables
        "taxpayersFilename"f"{script_dir}/../data/taxpayersdata.txt",
        # chemin absolu du fichier des résultats
        "resultsFilename"f"{script_dir}/../data/résultats.json",
        # chemin absolu du fichier des données de l'administration fiscale
        "admindataFilename"f"{script_dir}/../data/admindata.json"
    }
    # mise à jour du syspath
    from myutils import set_syspath

    set_syspath(absolute_dependencies)

    # on rend la config
    return config
  • ligne 8 : on met le dossier [shared] dans le Python Path. Ce dossier contient le module [impôts_module_02] utilisé par le script principal ;

11-2. Script principal [main.py]

Le script principal de la version 3 est le suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
# on configure l'application
import config

config = config.configure()

# le syspath est configuré - on peut faire les imports
from impôts_module_02 import calcul_impôt, get_admindata, get_taxpayers_data, record_results_in_json_file

# fichier des contribuables
taxpayers_filename = config['taxpayersFilename']
# fichier des résultats
results_filename = config['resultsFilename']
# fichier des données de l'administration fiscale
admindata_filename = config['admindataFilename']
# code
try:

    # lecture des données de l'administration fiscale
    admindata = get_admindata(admindata_filename)
    # lecture des données contribuables
    taxpayers = get_taxpayers_data(taxpayers_filename)
    # liste des résultats
    results = []
    # on calcule l'impôt des contribuables
    for taxpayer in taxpayers:
        # le calcul de l'impôt renvoie un dictionnaire de clés
        # ['marié', 'enfants', 'salaire', 'impôt', 'surcôte', 'décôte', 'réduction', 'taux']
        result = calcul_impôt(admindata, taxpayer['marié'], taxpayer['enfants'], taxpayer['salaire'])
        # le dictionnaire est ajouté à la liste des résultats
        results.append(result)
    # on enregistre les résultats
    record_results_in_json_file(results_filename, results)
except BaseException as erreur:
    # il peut y avoir différentes erreurs : absence de fichier, contenu de fichier incorrect
    # on affiche l'erreur et on quitte l'application
    print(f"L'erreur suivante s'est produite : {erreur}]\n")
finally:
    print("Travail terminé...")

Notes

  • lignes 2-4, on configure l’application notamment son Python Path ;

  • ligne 7 : on importe les fonctions dont on a besoin dans [main.py] ;

  • lignes 9-14 : les noms des fichiers exploités par l’application sont récupérés dans la configuration ;

  • le script principal de la version 3 présente trois différences vis à vis de celui des versions 1 et 2 :

    • ligne 21 : les données de l'administration fiscale sont prises dans le fichier jSON [./data/admindata.json] ;

    • ligne 32 : les résultats du calcul de l'impôt sont placés dans le fichier jSON [./data/résultats.json] ;

    • ligne 7 : les fonctions de la version 3 sont trouvées dans le module [impots.modules.impôts_module_02] ;

11-3. Le module [impots.v02.modules.impôts_module_02]

Le module [impots.v02.modules.impôts_module_02] a la structure suivante :

Image non disponible
  • on retrouve dans le module des fonctions déjà présentes dans le module utilisé par la version 1 avec cependant une différence. Lorsque le module de la version 2 reprend une fonction présente dans le module de la version 1, elle le fait avec un paramètre supplémentaire : [adminData] (lignes 29, 51, 77, 127). Ce paramètre représente le dictionnaire des données fiscales issues du fichier jSON [adminData.json]. Dans le module de la version 1, ces données n'avaient pas besoin d'être passées aux fonctions car elles étaient définies globalement à celles-ci ce qui faisait que les fonctions les connaissaient ;

11-4. Lecture des données de l'administration fiscale

La fonction [get_admindata] est la suivante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
# lecture des données de l'administration fiscale dans un fichier jSON
# ----------------------------------------
def get_admindata(admindata_filename: str) -> dict:
    # lecture des données de l'administration fiscale
    # on laisse remonter les éventuelles exceptions : absence du fichier, contenu jSON incorrect
    file = None
    try:
        # ouverture du fichier jSON en lecture
        file = codecs.open(admindata_filename, "r", "utf8")
        # transfert du contenu dans un dictionnaire
        admin_data = json.load(file)
        # on rend le résultat
        return admin_data
    finally:
        # fermeture du fichier s'il a été ouvert
        if file:
            file.close()
  • ligne 9 : on récupère le dictionnaire image du fichier jSON lu ;

11-5. Enregistrement des résultats

La fonction [record_results_in_json_file] est la suivante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
# écriture des résultats dans un fichier jSON
# ----------------------------------------
def record_results_in_json_file(results_filename: str, results: list):
    file = None
    try:
        # ouverture du fichier des résultats
        file = codecs.open(results_filename, "w", "utf8")
        # écriture en bloc
        json.dump(results, file, ensure_ascii=False)
    finally:
        # on ferme le fichier s'il a été ouvert
        if file:
            file.close()
  • ligne 7 : on crée un fichier encodé en UTF-8 ;

  • ligne 9 : on écrit la liste [results] dans le fichier jSON. Les caractères UTF-8 ne sont pas échappés (ensure_ascii=False) ;

11-6. Modification des fonctions

Certaines fonctions reçoivent désormais un paramètre [admin_data] supplémentaire. Cela modifie un peu leur écriture. Prenons par exemple la fonction [calcul_impôt] :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
# calcul de l'impôt - étape 1
# ----------------------------------------
def calcul_impôt(admin_data: dict, marié: str, enfants: int, salaire: int) -> dict:
    # marié : oui, non
    # enfants : nombre d'enfants
    # salaire : salaire annuel
    # limites, coeffr, coeffn : les tableaux des données permettant le calcul de l'impôt
    #
    # calcul de l'impôt avec enfants
    result1 = calcul_impôt_2(admin_data, marié, enfants, salaire)
    impot1 = result1["impôt"]
    # calcul de l'impôt sans les enfants
    if enfants != 0:
        result2 = calcul_impôt_2(admin_data, marié, 0, salaire)
        impot2 = result2["impôt"]
        # application du plafonnement du quotient familial
        if enfants < 3:
            # PLAFOND_QF_DEMI_PART euros pour les 2 premiers enfants
            impot2 = impot2 - enfants * admin_data['plafond_qf_demi_part']
        else:
            # PLAFOND_QF_DEMI_PART euros pour les 2 premiers enfants, le double pour les suivants
            impot2 = impot2 - 2 * admin_data['plafond_qf_demi_part'] - (enfants - 2) * 2 * admin_data[
                'plafond_qf_demi_part']
    else:
        impot2 = impot1
        result2 = result1

    # on prend l'impôt le plus fort avec le taux et la surcôte qui vont avec
    if impot1 > impot2:
        impot = impot1
        taux = result1["taux"]
        surcôte = result1["surcôte"]
    else:
        surcôte = impot2 - impot1 + result2["surcôte"]
        impot = impot2
        taux = result2["taux"]

    # calcul d'une éventuelle décôte
    décôte = get_décôte(admin_data, marié, salaire, impot)
    impot -= décôte
    # calcul d'une éventuelle réduction d'impôts
    réduction = get_réduction(admin_data, marié, salaire, enfants, impot)
    impot -= réduction
    # résultat
    return {"marié": marié, "enfants": enfants, "salaire": salaire, "impôt": math.floor(impot), "surcôte": surcôte,
            "décôte": décôte, "réduction": réduction, "taux": taux}

Notes

  • là où [calcul_impôt] appelle d'autres fonctions, elle passe [admin_data] en 1er paramètre (lignes 10, 14, 39, 42) ;

  • là où [calcul_impôt] utilise des constantes fiscales, elle passe désormais par le dictionnaire [admin_data] (lignes 19, 22) ;

Toutes les fonctions recevant [admin_data] comme paramètre, subissent ces mêmes types de modifications.

11-7. Résultats

Les résultats obtenus sont ceux présentés au début du paragraphe 8.3.


précédentsommairesuivant

Licence Creative Commons
Le contenu de cet article est rédigé par Serge Tahé et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2020 Developpez.com.