Skip to content

8. Exercício prático – versão 1

8.1. O problema

A tabela acima permite-nos calcular o imposto no caso simplificado de um contribuinte que apenas tem o seu salário a declarar. Conforme indicado na nota (1), o imposto calculado desta forma é o imposto antes de três mecanismos:

  • o limite do quociente familiar, que se aplica a rendimentos elevados;
  • o crédito fiscal e a redução fiscal que se aplicam aos rendimentos baixos;

Assim, o cálculo do imposto envolve os seguintes passos [http://impotsurlerevenu.org/comprendre-le-calcul-de-l-impot/1217-calcul-de-l-impot-2019.php]:

Image

Propomos escrever um programa para calcular o imposto de um contribuinte no caso simplificado de um contribuinte que tenha apenas o seu salário a declarar:

8.1.1. Cálculo do imposto bruto

O imposto bruto pode ser calculado da seguinte forma:

Primeiro, calculamos o número de quotas do contribuinte:

  • Cada progenitor contribui com 1 quota;
  • os dois primeiros filhos contribuem cada um com 1/2 quota;
  • os filhos subsequentes contribuem, cada um, com uma ação:

O número de quotas é, portanto:

  • nbParts=1+nbChildren*0,5+(nbChildren-2)*0,5 se o funcionário for solteiro;
  • nbParts=2+nbChildren*0,5+(nbChildren-2)*0,5 se for casado;
    • onde nbChildren é o número de filhos;
  • calculamos o rendimento tributável R = 0,9 * S, em que S é o salário anual;
  • O quociente familiar QF é calculado como QF = R / nbParts;
  • Calculamos o imposto bruto I com base nos seguintes dados (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

Cada linha tem 3 campos: campo1, campo2, campo3. Para calcular o imposto I, procuramos a primeira linha em que QF <= campo1 e retiramos os valores dessa linha. Por exemplo, para um funcionário casado com dois filhos e um salário anual S de 50 000 euros:

Rendimento tributável: R=0,9*S=45 000

Número de quotas: nbParts=2+2*0,5=3

Quociente familiar: QF = 45 000 / 3 = 15 000

A primeira linha em que QF <= campo1 é a seguinte:

    27519    0.14    1394.96

O Imposto I é então igual a 0,14*R – 1394,96*númeroDeAções=[0,14*45000-1394,96*3]=2115. O imposto é arredondado por defeito para o euro mais próximo.

Se a condição QF <= campo1 for verdadeira na primeira linha, então o imposto é zero.

Se QF for tal que a condição QF <= campo1 nunca seja satisfeita, então são utilizados os coeficientes da última linha. Aqui:

    0    0.45    20163.45

o que dá o imposto bruto I = 0,45*R – 20163,45*nbParts.

8.1.2. Limite do Quociente Familiar

Para determinar se o limite do quociente familiar (QF) se aplica, recalculamos o imposto bruto sem os filhos. Mais uma vez, para o trabalhador casado com dois filhos e um salário anual S de 50 000 euros:

Rendimento tributável: R = 0,9 * S = 45 000

Número de quotas: nbParts=2 (os filhos já não são contabilizados)

Quociente familiar: QF = 45 000 / 2 = 22 500

A primeira linha em que QF <= campo1 é a seguinte:

    27519    0.14    1394.96

O Imposto I é, então, igual a 0,14*R – 1394,96*número de ações = [0,14*45 000 – 1394,96*2] = 3510.

Benefício máximo relacionado com filhos: 1551 * 2 = 3102 euros

Imposto mínimo: 3.510 – 3.102 = 408 euros

O imposto bruto com 3 escalões de imposto, já calculado em 2.115 euros, é superior ao imposto mínimo de 408 euros, pelo que o limite familiar não se aplica neste caso.

De um modo geral, o imposto bruto é superior a (imposto1, imposto2), em que:

  • [imposto1]: é o imposto bruto calculado incluindo os filhos;
  • [imposto2]: é o imposto bruto calculado sem filhos e reduzido pelo crédito máximo (aqui 1.551 euros por meia quota) relativo aos filhos;

8.1.3. Cálculo da redução

Image

Continuando com o exemplo de um trabalhador casado com dois filhos e um salário anual S de 50 000 euros:

O imposto bruto (2.115) da etapa anterior é inferior a 2.627 euros para um casal (1.595 euros para uma pessoa solteira): a redução aplica-se, portanto. É calculada da seguinte forma:

desconto = limiar (casal = 1.970 / solteiro = 1.196) - 0,75 * imposto bruto

desconto = 1.970 – 0,75 * 2.115 = 383,75, arredondado para 384 euros.

Novo imposto bruto = 2.115 – 384 = 1.731 euros

8.1.4. Cálculo da redução fiscal

Image

Abaixo de um determinado limiar, é aplicada uma redução de 20% ao imposto bruto resultante dos cálculos anteriores. Em 2019, os limiares são os seguintes:

  • Solteiro: 21 037 euros;
  • casal: 42 074 euros; (o valor de 37 968 utilizado no exemplo acima parece estar incorreto);

Este limiar é aumentado pelo valor: 3.797 * (número de meias-partes contribuídas pelos filhos).

Mais uma vez, para o trabalhador casado com dois filhos e um salário anual S de 50 000 euros:

  • o seu rendimento tributável (45 000 euros) é inferior ao limiar (42 074 + 2 × 3 797) = 49 668 euros;
  • tem, portanto, direito a uma redução de 20% no seu imposto: 1.731 * 0,2 = 346,2 euros, arredondado para 347 euros;
  • o imposto bruto do contribuinte passa a ser: 1.731 – 347 = 1.384 euros;

8.1.5. Cálculo do imposto líquido

O nosso cálculo termina aqui: o imposto líquido a pagar será de 1 384 euros. Na realidade, o contribuinte poderá ter direito a outras deduções, nomeadamente por doações a organizações de interesse público ou geral.

8.1.6. Casos de rendimentos elevados

O nosso exemplo anterior aplica-se à maioria dos trabalhadores. No entanto, o cálculo do imposto difere para quem aufere rendimentos elevados.

8.1.6.1. Limite à redução de 10% sobre o rendimento anual

Na maioria dos casos, o rendimento tributável é calculado utilizando a fórmula: R = 0,9 × S, em que S é o salário anual. Isto é conhecido como a redução de 10%. Esta redução está limitada. Em 2019:

  • não pode exceder 12 502 euros;
  • não pode ser inferior a 437 euros;

Consideremos o caso de um trabalhador solteiro, sem filhos e com um salário anual de 200 000 euros:

  • a redução de 10% é de 200 000 euros > 12 502 euros. Por conseguinte, o limite máximo é de 12 502 euros;

8.1.6.2. Limite do Quociente Familiar

Vamos considerar um caso em que se aplica o limite familiar descrito na secção |Limite do Quociente Familiar|. Tomemos o caso de um casal com três filhos e um rendimento anual de 100 000 euros. Vamos rever os passos do cálculo:

  • a dedução de 10% é de 10 000 euros < 12 502 euros. O rendimento tributável R é, portanto, 100 000 - 10 000 = 90 000 euros;
  • o casal tem nbParts = 2 + 0,5 × 2 + 1 = 4 quotas;
  • o seu quociente familiar é, portanto, QF = R / nbParts = 90 000 / 4 = 22 500 euros;
  • o seu imposto bruto I1 com filhos é I1 = 0,14 × 90 000 – 1 394,96 × 4 = 7 020 euros;
  • o seu imposto bruto I2 sem filhos:
  • QF = 90 000 / 2 = 45 000 euros;
  • I2 = 0,3 × 90 000 – 5 798 × 2 = 15 404 euros;
  • a regra do limite do quociente familiar estabelece que o benefício proporcionado pelos filhos não pode exceder (1.551 × 4 meias quotas) = 6.204 euros. No entanto, neste caso, é I2 – I1 = 15.404 – 7.020 = 8.384 euros, o que é superior a 6.204 euros;
  • o imposto bruto é, portanto, recalculado como I3 = I2 - 6.204 = 15.404 - 6.204 = 9.200 euros;

Este casal não receberá nem crédito fiscal nem redução, e o seu imposto final será de 9 200 euros.

8.1.7. Dados oficiais

O cálculo dos impostos é complexo. Ao longo deste documento, os cálculos basear-se-ão nos seguintes exemplos. Os resultados provêm do simulador da administração fiscal |https://www3.impots.gouv.fr/simulateur/calcul_impot/2019/simplifie/index.htm|:

Contribuinte
Resultados oficiais
Resultados do algoritmo do documento
Casal com 2 filhos e um rendimento anual de 55 555 euros
Imposto = 2.815 euros
Taxa de imposto = 14%
Imposto = 2.814 euros
Taxa de imposto = 14%
Casal com 2 filhos e um rendimento anual de 50 000 euros ( )
Imposto = 1 385 euros
Crédito fiscal = 720 euros
Redução = 0 euros
Taxa de imposto = 14%
Imposto = 1.384 euros
Desconto = 384 euros
Crédito = 347 euros
Taxa de imposto = 14%
Casal com 3 filhos e um rendimento anual de 50 000 euros
Imposto = 0 euros
Crédito fiscal = 384 euros
Redução = 346 euros
Taxa de imposto = 14%
Imposto = 0 euros
Desconto = 720 euros
Dedução = 0 euros
Taxa de imposto = 14%
Solteiro com 2 filhos e um rendimento anual de 100 000 euros
Imposto = 19 884 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 41%
Imposto = 19 884 euros
Sobretaxa = 4.480 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 41%
Solteiro com 3 filhos e um rendimento anual de 100 000 euros
Imposto = 16 782 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 41%
Imposto = 16 782 euros
Sobretaxa = 7.176 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 41%
Casal com 3 filhos e um rendimento anual de 100 000 euros
Imposto = 9.200 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 30%
Imposto = 9.200 euros
Sobretaxa = 2.180 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 30%
Casal com 5 filhos e um rendimento anual de 100 000 euros
Imposto = 4.230 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 14%
Imposto = 4.230
Desconto = 0 euros
Dedução = 0 euros
Taxa de imposto = 14%
Solteiro, sem filhos e rendimento anual de 100 000 euros
Imposto = 22.986 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 41%
Imposto = 22 986 euros
Sobretaxa = 0 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 41%
Casal com 2 filhos e um rendimento anual de 30 000 euros
Imposto = 0 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 0%
Imposto = 0 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 0%
Solteiro, sem filhos e com um rendimento anual de 200 000 euros
Imposto = 64 211 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 45%
Imposto = 64 210 euros
Sobretaxa = 7.498 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 45%
Casal com 3 filhos e um rendimento anual de 200 000 euros
Imposto = 42 843 euros
Crédito fiscal = 0 euros
Dedução = 0 euros
Taxa de imposto = 41%
Imposto = 42 842 euros
Sobretaxa = 17 283 euros
Desconto = 0 euros
Redução = 0 euros
Taxa de imposto = 41%

No exemplo acima, a «sobretaxa» refere-se ao montante adicional pago pelos contribuintes com rendimentos elevados devido a dois fatores:

  • o limite máximo de 10 % da dedução do rendimento anual;
  • o limite máximo do abono de família;

Este indicador não pôde ser verificado porque o simulador da autoridade fiscal não o disponibiliza.

Podemos ver que o algoritmo do documento calcula sempre o montante correto do imposto, embora com uma margem de erro de 1 euro. Esta margem de erro resulta do arredondamento. Todos os montantes monetários são arredondados para o euro superior em alguns casos e para o euro inferior noutros. Como não estava familiarizado com as regras oficiais, os montantes monetários no algoritmo do documento foram arredondados:

  • para o euro superior no caso de descontos e reduções;
  • para baixo, para o euro mais próximo, no caso de sobretaxas e do imposto final;

Iremos desenvolver várias versões da aplicação de cálculo de impostos.

8.2. Versão 1

Image

8.2.1. O script principal

Apresentamos um programa inicial onde:

  • os dados necessários para calcular o imposto estão codificados no código como listas e constantes;
  • os dados do contribuinte (casado, filhos, salário) estão armazenados num primeiro ficheiro de texto [taxpayersdata.txt];
  • os resultados do cálculo do imposto (casado, filhos, salário, imposto) são armazenados num segundo ficheiro de texto [results.txt];

O script [v-01/main.py] é o seguinte:

#  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()

Notas

  • Linha 4: Utilizamos o módulo [impots.v01.modules.impôts_module_01]. Note-se que este caminho é relativo à raiz do projeto PyCharm;
  • linha 10: o ficheiro [data/taxpayersdata.txt] tem o seguinte conteúdo:
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

Cada linha representa uma tupla de três elementos [casado/em união de facto ou não, número de filhos, salário anual em euros].

  • Linha 12: o ficheiro onde serão colocados os resultados do cálculo de impostos para cada contribuinte do ficheiro [taxpayersdata.txt]. Terá o seguinte conteúdo:
{'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}
  • Linha 16: Recuperamos os dados dos contribuintes contidos em [taxpayersdata.txt]. Recuperamos uma lista de dicionários com as chaves [casado, filhos, salário], sendo que cada dicionário representa um contribuinte;
  • linhas 17–25: O imposto para os contribuintes da lista [taxPayers] é calculado. É devolvida uma lista [results], em que cada elemento é, mais uma vez, um dicionário com as chaves [casado, filhos, salário, imposto, sobretaxa, desconto, redução, taxa];
  • linha 27: a lista [results] é guardada no ficheiro [results.txt] no formato apresentado acima;
  • linhas 28–32: Capturamos todas as exceções que possam ser lançadas pelo módulo [impots.v01.modules.impôts_module_01];

Vamos agora detalhar as três funções utilizadas pelo script [main]:

  • [get_taxpayers_data]: para ler os dados dos contribuintes;
  • [calcul_impôt]: para calcular os seus impostos;
  • [record_results]: para guardar os resultados num ficheiro de texto;

Todas estas funções estão localizadas no módulo [impots.modules.impôts_module_01].

8.2.2. O módulo [impots.v01.shared.impôts_module_01]

As funções necessárias para o cálculo de impostos foram agrupadas no módulo [impots.v01.shared.impôts_module_01]:

Image

  • em [1]: definição das constantes de cálculo de impostos;
  • em [2]: a lista de funções do módulo;

8.2.3. A função [get_taxpayers_data]

A função [get_taxpayers_data] é a seguinte:

#  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()

Notas

  • linha 7: [taxpayers_filename] é o nome do ficheiro a ser processado. A função devolve uma lista;
  • linhas 18–24: o ciclo processa as linhas [married, children, salary] do ficheiro de texto;
  • linha 20: os três elementos da linha são recuperados. Partimos do princípio de que a linha está sintaticamente correta, ou seja, que contém efetivamente os três elementos esperados;
  • linha 22: é construído um dicionário com as chaves [married, children, salary], e este dicionário é adicionado à lista [taxPayers];
  • linha 26: assim que o ficheiro tiver sido processado, a lista [taxPayers] é devolvida;
  • Linhas 10–30: Note-se que não foi adicionada nenhuma cláusula [catch] ao bloco [try] na linha 10. A cláusula [catch] não é obrigatória. Na linha 27, foi adicionada uma cláusula [finally] para fechar o ficheiro de texto em todos os casos, ocorra ou não um erro;
  • esta estrutura try/finally permite que uma potencial exceção escape (não há catch). Esta exceção propagar-se-á para o script principal [main], que irá parar e exibir a exceção (ver secção |O Script Principal|). Este mecanismo foi utilizado na maioria das funções do módulo;

8.2.4. A função [calcul_impôt]

A função [calcul_impôt] é a seguinte:

#  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}

Notas

  • linhas 6–8: escalões de imposto (ver secção |Cálculo do Imposto Bruto|);
  • linhas 11–20: constantes para o cálculo do imposto;
  • Note-se que os elementos inicializados nas linhas 5–20 serão globais para as funções que estamos prestes a descrever. São, portanto, conhecidos desde que a função que os utiliza não declare variáveis com os mesmos nomes;
  • os valores nas linhas 5–20 mudam todos os anos. Aqui, são os valores de 2019;
  • linha 25: a função [calculate_tax] recebe três parâmetros:
    • [married]: sim/não, indica se o contribuinte é casado ou vive em união de facto;
    • [children]: o número de filhos;
    • [salary]: o seu salário anual em euros;
  • linhas 31–33: cálculo do imposto tendo em conta os filhos;
  • linhas 34–47: estas linhas implementam o limite máximo do quociente familiar (ver secção |Limite máximo do quociente familiar|);
  • linhas 49–57: estas linhas calculam a taxa de imposto do contribuinte, bem como qualquer sobretaxa (ver secção |Casos de rendimentos elevados|);
  • linhas 59–61: cálculo de qualquer crédito fiscal (ver secção |Cálculo do crédito fiscal|);
  • linhas 62–64: cálculo de qualquer redução do imposto devido (ver secção |Cálculo da redução do imposto|);

O algoritmo é bastante complexo e não entraremos em mais detalhes do que os fornecidos nos comentários. O algoritmo implementa o método de cálculo do imposto conforme descrito na secção |O Problema|.

8.2.5. A função [calcul_tax_2]

A função [calcul_impôt] chama a seguinte função [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]}

Este algoritmo foi descrito na Secção 8.1.1.

8.2.6. A função [get_discount]

A função [get_discount] implementa o cálculo de qualquer desconto fiscal (secção |Cálculo do desconto|):

#  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. A função [get_reduction]

A função [get_reduction] implementa o cálculo de qualquer redução fiscal (secção |Cálculo da redução fiscal|):

#  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. A função [get_taxable_income]

A função [get_taxable_income] calcula o rendimento tributável com base no salário anual:

#  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. A função [record_results]

A função [record_results] guarda os resultados do cálculo do imposto num ficheiro de texto:

#  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. Os resultados

Como mencionado anteriormente, com o seguinte ficheiro de contribuintes [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

O script [main.py] cria o seguinte ficheiro [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}

Estes resultados correspondem aos dados oficiais apresentados na secção |Dados Oficiais|.

Agora, vamos executar esta versão numa janela de 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'

Encontramos um erro que já vimos antes: um em que um módulo não pode ser encontrado, neste caso o módulo [impots]. Lembre-se de que isto significa:

  • o interpretador Python pesquisou os diretórios no Python Path um por um;
  • em nenhum deles encontrou um diretório contendo um script [impots.py];

A versão [v02] irá fornecer uma solução para este problema.