Skip to content

8. Esercizio pratico – versione 1

8.1. Il problema

La tabella sopra riportata ci permette di calcolare l'imposta nel caso semplificato di un contribuente che deve dichiarare solo il proprio stipendio. Come indicato nella nota (1), l'imposta calcolata in questo modo è l'imposta al lordo di tre meccanismi:

  • il limite del quoziente familiare, che si applica ai redditi elevati;
  • il credito d'imposta e la riduzione d'imposta che si applicano ai redditi bassi;

Pertanto, il calcolo dell'imposta prevede le seguenti fasi [http://impotsurlerevenu.org/comprendre-le-calcul-de-l-impot/1217-calcul-de-l-impot-2019.php]:

Image

Proponiamo di scrivere un programma per calcolare l'imposta di un contribuente nel caso semplificato di un contribuente che ha solo lo stipendio da dichiarare:

8.1.1. Calcolo dell'imposta lorda

L'imposta lorda può essere calcolata come segue:

Per prima cosa, calcoliamo il numero di quote del contribuente:

  • Ciascun genitore contribuisce con 1 quota;
  • i primi due figli contribuiscono ciascuno con 1/2 quota;
  • i figli successivi contribuiscono ciascuno con una quota:

Il numero di quote è quindi:

  • nbParts=1+nbChildren*0,5+(nbChildren-2)*0,5 se il dipendente è celibe/nubile;
  • nbParts=2+nbChildren*0,5+(nbChildren-2)*0,5 se è sposato;
    • dove nbFigli è il numero di figli;
  • si calcola il reddito imponibile R = 0,9 * S, dove S è lo stipendio annuo;
  • Il quoziente familiare QF si calcola come QF = R / nbParts;
  • Calcoliamo l'imposta lorda I sulla base dei seguenti dati (2019):
9964
0
0
27.519
0,14
1.394,96
73.779
0,3
5.798
156.244
0,4
13.913,69
0
0,45
20163,45

Ogni riga ha 3 campi: campo1, campo2, campo3. Per calcolare l'imposta I, cerchiamo la prima riga in cui QF <= campo1 e prendiamo i valori da quella riga. Ad esempio, per un dipendente sposato con due figli e uno stipendio annuo S di 50.000 euro:

Reddito imponibile: R=0,9*S=45.000

Numero di quote: nbParts=2+2*0,5=3

Quoziente familiare: QF = 45.000 / 3 = 15.000

La prima riga in cui QF <= campo1 è la seguente:

    27519    0.14    1394.96

L'imposta I è quindi pari a 0,14*R – 1394,96*numeroDiAzioni=[0,14*45000-1394,96*3]=2115. L'imposta viene arrotondata per difetto all'euro più vicino.

Se nella prima riga si verifica la condizione QF <= campo1, l'imposta è pari a zero.

Se QF è tale che la condizione QF <= campo1 non è mai soddisfatta, vengono utilizzati i coefficienti dell'ultima riga. Qui:

    0    0.45    20163.45

il che dà l'imposta lorda I = 0,45*R – 20163,45*nbParts.

8.1.2. Limite del quoziente familiare

Per determinare se si applica il limite del quoziente familiare (QF), ricalcoliamo l'imposta lorda senza i figli. Ancora una volta, per il dipendente sposato con due figli e uno stipendio annuo S di 50.000 euro:

Reddito imponibile: R = 0,9 * S = 45.000

Numero di quote: nbParts=2 (i figli non vengono più conteggiati)

Quoziente familiare: QF = 45.000 / 2 = 22.500

La prima riga in cui QF <= campo1 è la seguente:

    27519    0.14    1394.96

L'imposta I è quindi pari a 0,14*R – 1394,96*numero di azioni = [0,14*45.000 – 1394,96*2] = 3.510.

Indennità massima per figli a carico: 1551 * 2 = 3102 euro

Imposta minima: 3.510 – 3.102 = 408 euro

L'imposta lorda con 3 scaglioni fiscali, già calcolata a 2.115 euro, è superiore all'imposta minima di 408 euro, quindi in questo caso non si applica il limite familiare.

In generale, l'imposta lorda è maggiore di (imposta1, imposta2) dove:

  • [imposta1]: è l'imposta lorda calcolata includendo i figli;
  • [imposta2]: è l'imposta lorda calcolata senza figli e ridotta del credito massimo (in questo caso 1.551 euro per metà quota) relativo ai figli;

8.1.3. Calcolo della riduzione

Image

Utilizzando ancora l'esempio di un dipendente sposato con due figli e uno stipendio annuo S di 50.000 euro:

L'imposta lorda (2.115) del passaggio precedente è inferiore a 2.627 euro per una coppia (1.595 euro per una persona sola): si applica quindi la riduzione. Essa viene calcolata come segue:

sconto = soglia (coppia = 1.970 / single = 1.196) - 0,75 * imposta lorda

sconto = 1.970 – 0,75 * 2.115 = 383,75, arrotondato a 384 euro.

Nuova imposta lorda = 2.115 – 384 = 1.731 euro

8.1.4. Calcolo della riduzione fiscale

Image

Al di sotto di una certa soglia, viene applicata una riduzione del 20% all'imposta lorda risultante dai calcoli precedenti. Nel 2019, le soglie sono le seguenti:

  • Single: 21.037 euro;
  • coppia: 42.074 euro; (la cifra 37.968 utilizzata nell'esempio sopra riportato sembra essere errata);

Questa soglia viene aumentata del valore: 3.797 * (numero di quote pari alla metà versate dai figli).

Ancora una volta, per il dipendente sposato con due figli e uno stipendio annuo S di 50.000 euro:

  • il suo reddito imponibile (45.000 euro) è inferiore alla soglia (42.074 + 2 × 3.797) = 49.668 euro;
  • ha quindi diritto a una riduzione del 20% della sua imposta: 1.731 * 0,2 = 346,2 euro, arrotondati a 347 euro;
  • l'imposta lorda del contribuente diventa: 1.731 – 347 = 1.384 euro;

8.1.5. Calcolo dell'imposta netta

Il nostro calcolo si conclude qui: l'imposta netta dovuta sarà di 1.384 euro. In realtà, il contribuente potrebbe avere diritto ad altre detrazioni, in particolare per le donazioni a enti pubblici o di interesse generale.

8.1.6. Casi di redditi elevati

Il nostro esempio precedente si applica alla maggior parte dei lavoratori dipendenti. Tuttavia, il calcolo dell'imposta è diverso per i redditi elevati.

8.1.6.1. Limite massimo alla riduzione del 10% sul reddito annuo

Nella maggior parte dei casi, il reddito imponibile viene calcolato utilizzando la formula: R = 0,9 × S, dove S è lo stipendio annuale. Questa è nota come riduzione del 10%. Tale riduzione è soggetta a un limite massimo. Nel 2019:

  • non può superare i 12.502 euro;
  • non può essere inferiore a 437 euro;

Consideriamo il caso di un dipendente non sposato, senza figli e con uno stipendio annuo di 200.000 euro:

  • la riduzione del 10% è pari a 200.000 euro > 12.502 euro. Il limite massimo è quindi fissato a 12.502 euro;

8.1.6.2. Limite del quoziente familiare

Consideriamo un caso in cui si applica il limite familiare descritto nella sezione |Limite del quoziente familiare|. Prendiamo il caso di una coppia con tre figli e un reddito annuo di 100.000 euro. Ripassiamo i passaggi del calcolo:

  • la detrazione del 10% è pari a 10.000 euro < 12.502 euro. Il reddito imponibile R è quindi pari a 100.000 - 10.000 = 90.000 euro;
  • la coppia ha nbParts = 2 + 0,5 × 2 + 1 = 4 quote;
  • il loro quoziente familiare è quindi QF = R / nbParts = 90.000 / 4 = 22.500 euro;
  • la loro imposta lorda I1 con figli è I1 = 0,14 × 90.000 – 1.394,96 × 4 = 7.020 euro;
  • la loro imposta lorda I2 senza figli:
  • QF = 90.000 / 2 = 45.000 euro;
  • I2 = 0,3 × 90.000 – 5.798 × 2 = 15.404 euro;
  • la regola del limite massimo del quoziente familiare stabilisce che il beneficio fornito dai figli non può superare (1.551 × 4 mezze quote) = 6.204 euro. Tuttavia, in questo caso, si ha I2 – I1 = 15.404 – 7.020 = 8.384 euro, che è superiore a 6.204 euro;
  • l'imposta lorda viene quindi ricalcolata come I3 = I2 - 6.204 = 15.404 - 6.204 = 9.200 euro;

Questa coppia non riceverà né un credito d'imposta né una riduzione, e la loro imposta finale sarà di 9.200 euro.

8.1.7. Dati ufficiali

Il calcolo delle imposte è complesso. In questo documento, i calcoli si baseranno sui seguenti esempi. I risultati provengono dal simulatore dell'autorità fiscale |https://www3.impots.gouv.fr/simulateur/calcul_impot/2019/simplifie/index.htm|:

Contribuente
Risultati ufficiali
Risultati dell'algoritmo del documento
Coppia con 2 figli e un reddito annuo di 55.555 euro
Imposta = 2.815 euro
Aliquota fiscale = 14%
Imposta = 2.814 euro
Aliquota fiscale = 14%
Coppia con 2 figli e un reddito annuo di 50.000 euro ( )
Imposta = 1.385 euro
Credito d'imposta = 720 euro
Riduzione = 0 euro
Aliquota fiscale = 14%
Imposta = 1.384 euro
Sconto = 384 euro
Credito = 347 euro
Aliquota fiscale = 14%
Coppia con 3 figli e un reddito annuo di 50.000 euro
Imposta = 0 euro
Credito d'imposta = 384 euro
Riduzione = 346 euro
Aliquota fiscale = 14%
Imposta = 0 euro
Sconto = 720 euro
Detrazione = 0 euro
Aliquota fiscale = 14%
Single con 2 figli e un reddito annuo di 100.000 euro
Imposta = 19.884 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 41%
Imposta = 19.884 euro
Sovrattassa = 4.480 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 41%
Single con 3 figli e un reddito annuo di 100.000 euro
Imposta = 16.782 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 41%
Imposta = 16.782 euro
Sovrattassa = 7.176 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 41%
Coppia con 3 figli e un reddito annuo di 100.000 euro
Imposta = 9.200 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 30%
Imposta = 9.200 euro
Sovrattassa = 2.180 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 30%
Coppia con 5 figli e un reddito annuo di 100.000 euro
Imposta = 4.230 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 14%
Imposta = 4.230
Sconto = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 14%
Celibe, senza figli e reddito annuo di 100.000 euro
Imposta = 22.986 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 41%
Imposta = 22.986 euro
Sovrattassa = 0 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 41%
Coppia con 2 figli e un reddito annuo di 30.000 euro
Imposta = 0 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 0%
Imposta = 0 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 0%
Single senza figli e con un reddito annuo di 200.000 euro
Imposta = 64.211 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 45%
Imposta = 64.210 euro
Sovrattassa = 7.498 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 45%
Coppia con 3 figli e un reddito annuo di 200.000 euro
Imposta = 42.843 euro
Credito d'imposta = 0 euro
Detrazione = 0 euro
Aliquota fiscale = 41%
Imposta = 42.842 euro
Sovrattassa = 17.283 euro
Sconto = 0 euro
Riduzione = 0 euro
Aliquota fiscale = 41%

Nell'esempio sopra riportato, il termine "sovrapprezzo" si riferisce all'importo aggiuntivo pagato dai redditi più elevati a causa di due fattori:

  • il limite massimo del 10% sulla detrazione dal reddito annuo;
  • il limite massimo dell'assegno familiare;

Questo indicatore non ha potuto essere verificato poiché il simulatore dell'autorità fiscale non lo fornisce.

Si può notare che l’algoritmo del documento calcola ogni volta l’importo corretto dell’imposta, sebbene con un margine di errore di 1 euro. Questo margine di errore deriva dall’arrotondamento. Tutti gli importi monetari vengono arrotondati per eccesso all’euro più vicino in alcuni casi e per difetto all’euro più vicino in altri. Poiché non conoscevo le regole ufficiali, gli importi monetari nell’algoritmo del documento sono stati arrotondati:

  • per arrotondamento per eccesso all'euro successivo per sconti e riduzioni;
  • per difetto all'euro più vicino per i supplementi e l'imposta finale;

Svilupperemo diverse versioni dell'applicazione per il calcolo delle imposte.

8.2. Versione 1

Image

8.2.1. Lo script principale

Presentiamo un programma iniziale in cui:

  • i dati necessari per calcolare l'imposta sono hard-coded nel codice sotto forma di elenchi e costanti;
  • i dati del contribuente (stato civile, figli, stipendio) sono memorizzati in un primo file di testo [taxpayersdata.txt];
  • i risultati del calcolo dell'imposta (stato civile, figli, stipendio, imposta) sono memorizzati in un secondo file di testo [results.txt];

Lo script [v-01/main.py] è il seguente:

#  modules
import sys

from impots.v01.shared.impôts_module_01 import *

#  hand -----------------------

#  constants
#  taxpayer file
DATA = "./data/taxpayersdata.txt"
#  results file
RESULTATS = "./data/résultats.txt"

try:
    #  reading taxpayer data
    tax_payers = get_taxpayers_data(DATA)
    #  results list
    results = []
    #  taxpayers' taxes are calculated
    for tax_payer in tax_payers:
        #  tax calculation returns a dictionary of keys
        #  ['married', 'children', 'salary', 'tax', 'surcôte', 'décôte', 'réduction', 'taux']
        result = calcul_impôt(tax_payer['marié'], tax_payer['enfants'], tax_payer['salaire'])
        #  the dictionary is added to the list of results
        results.append(result)
    #  we record the results
    record_results(RESULTATS, results)
except BaseException as erreur:
    #  there may be various errors: no file, incorrect file content
    #  display the error and exit the application
    print(f"l'erreur suivante s'est produite : {erreur}]\n")
    sys.exit()

Note

  • Riga 4: Utilizziamo il modulo [impots.v01.modules.impôts_module_01]. Si noti che questo percorso è relativo alla radice del progetto PyCharm;
  • riga 10: il file [data/taxpayersdata.txt] è il seguente:
oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

Ogni riga rappresenta una tupla composta da tre elementi [stato civile (coniugato/unione civile o meno), numero di figli, stipendio annuo in euro].

  • Riga 12: il file in cui verranno inseriti i risultati del calcolo delle imposte per ciascun contribuente presente nel file [taxpayersdata.txt]. Il file avrà il seguente contenuto:
{'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': 50000, 'impôt': 0, 'surcôte': 0, 'décôte': 720, 'réduction': 0, 'taux': 0.14}
{'marié': 'non', 'enfants': 2, 'salaire': 100000, 'impôt': 19884, 'surcôte': 4480, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'non', 'enfants': 3, 'salaire': 100000, 'impôt': 16782, 'surcôte': 7176, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'oui', 'enfants': 3, 'salaire': 100000, 'impôt': 9200, 'surcôte': 2180, 'décôte': 0, 'réduction': 0, 'taux': 0.3}
{'marié': 'oui', 'enfants': 5, 'salaire': 100000, 'impôt': 4230, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0.14}
{'marié': 'non', 'enfants': 0, 'salaire': 100000, 'impôt': 22986, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'oui', 'enfants': 2, 'salaire': 30000, 'impôt': 0, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0}
{'marié': 'non', 'enfants': 0, 'salaire': 200000, 'impôt': 64210, 'surcôte': 7498, 'décôte': 0, 'réduction': 0, 'taux': 0.45}
{'marié': 'oui', 'enfants': 3, 'salaire': 200000, 'impôt': 42842, 'surcôte': 17283, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
  • Riga 16: Recuperiamo i dati dei contribuenti contenuti in [taxpayersdata.txt]. Recuperiamo un elenco di dizionari con chiavi [married, children, salary], dove ogni dizionario rappresenta un contribuente;
  • righe 17–25: viene calcolata l'imposta per i contribuenti nell'elenco [taxPayers]. Viene restituito un elenco [results], in cui ogni elemento è a sua volta un dizionario con le chiavi [married, children, salary, tax, surcharge, discount, reduction, rate];
  • riga 27: l'elenco [results] viene salvato nel file [results.txt] nel formato mostrato sopra;
  • righe 28–32: Intercettiamo tutte le eccezioni che potrebbero essere generate dal modulo [impots.v01.modules.impôts_module_01];

Ora descriveremo in dettaglio le tre funzioni utilizzate dallo script [main]:

  • [get_taxpayers_data]: per leggere i dati dei contribuenti;
  • [calcul_impôt]: per calcolare le loro imposte;
  • [record_results]: per salvare i risultati in un file di testo;

Tutte queste funzioni si trovano nel modulo [impots.modules.impôts_module_01].

8.2.2. Il modulo [impots.v01.shared.impôts_module_01]

Le funzioni necessarie per il calcolo delle imposte sono state raggruppate nel modulo [impots.v01.shared.impôts_module_01]:

Image

  • in [1]: definizione delle costanti di calcolo delle imposte;
  • in [2]: l'elenco delle funzioni del modulo;

8.2.3. La funzione [get_taxpayers_data]

La funzione [get_taxpayers_data] è la seguente:

#  imports
import codecs


#  reading taxpayer data
# ----------------------------------------
def get_taxpayers_data(taxpayers_filename: str) -> list:
    #  reading taxpayer data
    file = None
    try:
        #  list of taxpayers
        taxpayers = []
        #  open file
        file = codecs.open(taxpayers_filename, "r", "utf8")
        #  read the first line of the taxpayer file
        ligne = file.readline().strip()
        #  as long as there's a line left to operate
        while ligne != '':
            #  we retrieve the 3 fields married,children,salary which form the line
            (marié, enfants, salaire) = ligne.split(",")
            #  we add them to the list of taxpayers
            taxpayers.append({'marié': marié.strip().lower(), 'enfants': int(enfants), 'salaire': int(salaire)})
            #  a new line is read from the taxpayer file
            ligne = file.readline().strip()
        #  we return the result
        return taxpayers
    finally:
        #  close the file if it has been opened
        if file:
            file.close()

Note

  • riga 7: [taxpayers_filename] è il nome del file da elaborare. La funzione restituisce una lista;
  • righe 18–24: il ciclo elabora le righe [married, children, salary] del file di testo;
  • riga 20: vengono recuperati i tre elementi della riga. Si presume qui che la riga sia sintatticamente corretta, ovvero che contenga effettivamente i tre elementi previsti;
  • riga 22: viene costruito un dizionario con le chiavi [married, children, salary], e questo dizionario viene aggiunto alla lista [taxPayers];
  • riga 26: una volta elaborato il file, viene restituita la lista [taxPayers];
  • Righe 10–30: Si noti che non è stata aggiunta alcuna clausola [catch] al blocco [try] alla riga 10. La clausola [catch] non è obbligatoria. Alla riga 27, è stata aggiunta una clausola [finally] per chiudere il file di testo in tutti i casi, indipendentemente dal verificarsi o meno di un errore;
  • questa struttura try/finally consente a una potenziale eccezione di sfuggire (non c'è catch). Questa eccezione si propagherà allo script principale [main], che si interromperà e visualizzerà l'eccezione (vedi sezione |Lo script principale|). Questo meccanismo è stato utilizzato per la maggior parte delle funzioni del modulo;

8.2.4. La funzione [calcul_impôt]

La funzione [calcul_impôt] è la seguente:

#  imports
import codecs
import math

#  2019 tax brackets
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]

#  constant for 2019 tax calculation
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


#  tAX CALCULATION
# ----------------------------------------
def calcul_impôt(marié: str, enfants: int, salaire: int) -> dict:
    #  married: yes, no
    #  children: number of children
    #  salary: annual salary
    #  limits, coeffr, coeffn: data tables for tax calculation
    #
    #  tax calculation with children
    result1 = calcul_impôt_2(marié, enfants, salaire)
    impot1 = result1["impôt"]
    #  tax calculation without children
    if enfants != 0:
        result2 = calcul_impôt_2(marié, 0, salaire)
        impot2 = result2["impôt"]
        #  application of the family allowance ceiling
        if enfants < 3:
            #  PLAFOND_QF_DEMI_PART euros for the first 2 children
            impot2 = impot2 - enfants * PLAFOND_QF_DEMI_PART
        else:
            #  PLAFOND_QF_DEMI_PART euros for the first 2 children, double for subsequent children
            impot2 = impot2 - 2 * PLAFOND_QF_DEMI_PART - (enfants - 2) * 2 * PLAFOND_QF_DEMI_PART
    else:
        impot2 = impot1
        result2 = result1

    #  we take the highest tax with the rate and surcharge that go with it
    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"]

    #  calculation of any discount
    décôte = get_décôte(marié, salaire, impot)
    impot -= décôte
    #  calculation of any tax reduction
    réduction = get_réduction(marié, salaire, enfants, impot)
    impot -= réduction
    #  result
    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}

Note

  • righe 6–8: scaglioni fiscali (vedi sezione |Calcolo dell'imposta lorda|);
  • righe 11–20: costanti per il calcolo dell'imposta;
  • Si noti che gli elementi inizializzati nelle righe 5–20 saranno globali per le funzioni che stiamo per descrivere. Sono quindi noti fintanto che la funzione che li utilizza non dichiara variabili con gli stessi nomi;
  • i dati nelle righe 5–20 cambiano ogni anno. Qui sono riportati i dati relativi al 2019;
  • riga 25: la funzione [calculate_tax] accetta tre parametri:
    • [married]: sì/no, indica se il contribuente è sposato o in unione civile;
    • [children]: il numero di figli;
    • [salary]: il loro stipendio annuale in euro;
  • righe 31–33: calcolo delle imposte tenendo conto dei figli;
  • righe 34–47: queste righe applicano il limite massimo al quoziente familiare (vedi sezione |Limite massimo al quoziente familiare|);
  • righe 49–57: queste righe calcolano l’aliquota fiscale del contribuente e l’eventuale sovrattassa (vedi sezione |Casi di reddito elevato|);
  • righe 59–61: calcolo di eventuali crediti d'imposta (vedere la sezione |Calcolo del credito d'imposta|);
  • righe 62–64: calcolo di eventuali riduzioni dell'imposta dovuta (vedere la sezione |Calcolo della riduzione d'imposta|);

L'algoritmo è piuttosto complesso e non entreremo in maggiori dettagli rispetto a quanto fornito nei commenti. L'algoritmo implementa il metodo di calcolo dell'imposta descritto nella sezione |Il problema|.

8.2.5. La funzione [calcul_tax_2]

La funzione [calcul_impôt] chiama la seguente funzione [calcul_impôt_2]:

def calcul_impôt_2(marié: str, enfants: int, salaire: int) -> list:
    #  married: yes, no
    #  children: number of children
    #  salary: annual salary
    #  limits, coeffr, coeffn: data tables for tax calculation
    #
    #  number of shares
    marié = marié.strip().lower()
    if marié == "oui":
        nb_parts = enfants / 2 + 2
    else:
        nb_parts = enfants / 2 + 1

    #  1 part per child from the 3rd
    if enfants >= 3:
        #  an additional half share for each child from the 3rd onwards
        nb_parts += 0.5 * (enfants - 2)

    #  taxable income
    revenu_imposable = get_revenu_imposable(salaire)
    #  surcharge
    surcôte = math.floor(revenu_imposable - 0.9 * salaire)
    #  for rounding problems
    if surcôte < 0:
        surcôte = 0

    #  family quotient
    quotient = revenu_imposable / nb_parts
    #  is set at the end of the limit table to stop the following loop
    limites[len(limites) - 1] = quotient
    #  tAX CALCULATION
    i = 0
    while quotient > limites[i]:
        i += 1
        #  because we've placed quotient at the end of the limit array, the previous loop
    #  cannot go beyond the limit table

    #  now we can calculate the tax
    impôt = math.floor(revenu_imposable * coeffr[i] - nb_parts * coeffn[i])
    #  result
    return {"impôt": impôt, "surcôte": surcôte, "taux": coeffr[i]}

Questo algoritmo è stato descritto nella Sezione 8.1.1.

8.2.6. La funzione [get_discount]

La funzione [get_discount] implementa il calcolo di eventuali sconti fiscali (sezione |Calcolo dello sconto|):

#  calculates any discount
def get_décôte(marié: str, salaire: int, impots: int) -> int:
    #  at the outset, a zero discount
    décôte = 0
    #  maximum tax amount to qualify for discount
    plafond_impôt_pour_décôte = PLAFOND_IMPOT_COUPLE_POUR_DECOTE if marié == "oui" else PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE
    if impots < plafond_impôt_pour_décôte:
        #  maximum discount
        plafond_décôte = PLAFOND_DECOTE_COUPLE if marié == "oui" else PLAFOND_DECOTE_CELIBATAIRE
        #  theoretical discount
        décôte = plafond_décôte - 0.75 * impots
        #  the discount cannot exceed the amount of tax due
        if décôte > impots:
            décôte = impots

        #  no discount <0
        if décôte < 0:
            décôte = 0

    #  result
    return math.ceil(décôte)

8.2.7. La funzione [get_reduction]

La funzione [get_reduction] implementa il calcolo di eventuali riduzioni fiscali (sezione |Calcolo della riduzione fiscale|):

#  calculates any reduction
def get_réduction(marié: str, salaire: int, enfants: int, impots: int) -> int:
    #  the income ceiling to qualify for the 20% reduction
    plafond_revenu_pour_réduction = PLAFOND_REVENUS_COUPLE_POUR_REDUCTION if marié == "oui" else PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION
    plafond_revenu_pour_réduction += enfants * VALEUR_REDUC_DEMI_PART
    if enfants > 2:
        plafond_revenu_pour_réduction += (enfants - 2) * VALEUR_REDUC_DEMI_PART

    #  taxable income
    revenu_imposable = get_revenu_imposable(salaire)
    #  reduction
    réduction = 0
    if revenu_imposable < plafond_revenu_pour_réduction:
        #  20% discount
        réduction = 0.2 * impots

    #  result
    return math.ceil(réduction)

8.2.8. La funzione [get_taxable_income]

La funzione [get_taxable_income] calcola il reddito imponibile in base allo stipendio annuale:

#  revenu_imposable = salaireAnnuel - allowance
#  the allowance has a minimum and a maximum
# ----------------------------------------
def get_revenu_imposable(salaire: int) -> int:
    #  10% salary deduction
    abattement = 0.1 * salaire
    #  this allowance may not exceed ABATTEMENT_DIXPOURCENT_MAX
    if abattement > ABATTEMENT_DIXPOURCENT_MAX:
        abattement = ABATTEMENT_DIXPOURCENT_MAX

    #  the allowance cannot be less than ABATTEMENT_DIXPOURCENT_MIN
    if abattement < ABATTEMENT_DIXPOURCENT_MIN:
        abattement = ABATTEMENT_DIXPOURCENT_MIN

    #  taxable income
    revenu_imposable = salaire - abattement
    #  result
    return math.floor(revenu_imposable)

8.2.9. La funzione [record_results]

La funzione [record_results] salva i risultati del calcolo delle imposte in un file di testo:

#  writing results to a text file
# ----------------------------------------
def record_results(results_filename: str, results: list):
    #  results_filename: the name of the text file in which to place the results
    #  results: the results list in the form of a dictionary list
    #  each dictionary is written on a line of text
    résultats = None
    try:
        #  opening the results file
        résultats = codecs.open(results_filename, "w", "utf8")
        #  taxpayer exploitation
        for result in results:
            #  enter the result in the results file
            résultats.write(f"{result}\n")
            #  next taxpayer
    finally:
        #  close the file if it has been opened
        if résultats:
            résultats.close()

8.2.10. I risultati

Come accennato in precedenza, con il seguente file dei contribuenti [taxpayersdata.txt]:

oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

Lo script [main.py] crea il seguente file [results.txt]:

{'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': 50000, 'impôt': 0, 'surcôte': 0, 'décôte': 720, 'réduction': 0, 'taux': 0.14}
{'marié': 'non', 'enfants': 2, 'salaire': 100000, 'impôt': 19884, 'surcôte': 4480, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'non', 'enfants': 3, 'salaire': 100000, 'impôt': 16782, 'surcôte': 7176, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'oui', 'enfants': 3, 'salaire': 100000, 'impôt': 9200, 'surcôte': 2180, 'décôte': 0, 'réduction': 0, 'taux': 0.3}
{'marié': 'oui', 'enfants': 5, 'salaire': 100000, 'impôt': 4230, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0.14}
{'marié': 'non', 'enfants': 0, 'salaire': 100000, 'impôt': 22986, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0.41}
{'marié': 'oui', 'enfants': 2, 'salaire': 30000, 'impôt': 0, 'surcôte': 0, 'décôte': 0, 'réduction': 0, 'taux': 0}
{'marié': 'non', 'enfants': 0, 'salaire': 200000, 'impôt': 64210, 'surcôte': 7498, 'décôte': 0, 'réduction': 0, 'taux': 0.45}
{'marié': 'oui', 'enfants': 3, 'salaire': 200000, 'impôt': 42842, 'surcôte': 17283, 'décôte': 0, 'réduction': 0, 'taux': 0.41}

Questi risultati corrispondono ai dati ufficiali riportati nella sezione |Dati ufficiali|.

Ora, eseguiamo questa versione in una finestra di console:


(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01>python main.py
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    from impots.v01.shared.impôts_module_01 import *
ModuleNotFoundError: No module named 'impots'

Si verifica un errore già visto in precedenza: un modulo non è stato trovato, in questo caso il modulo [impots]. Ricordiamo che ciò significa:

  • l'interprete Python ha cercato una per una le directory nel Python Path;
  • in nessuna di esse ha trovato una directory contenente uno script [impots.py];

La versione [v02] fornirà una soluzione a questo problema.