Skip to content

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

8.1. O problema

Image

A tabela acima permite calcular o imposto no caso simplificado de um contribuinte que tenha apenas seu salário a declarar. Conforme indicado na nota (1), o imposto assim calculado é o imposto antes da aplicação de três mecanismos:

  • o teto do quociente familiar, que se aplica a rendas elevadas;
  • o abatimento e a redução de impostos, que se aplicam a rendas baixas;

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

Image

Propõe-se escrever um programa que permita calcular o imposto de um contribuinte no caso simplificado de um contribuinte que tenha apenas seu salário a declarar:

8.1.1. Cálculo do imposto bruto

O imposto bruto pode ser calculado da seguinte maneira:

Primeiro, calcula-se o número de cotas do contribuinte:

  • cada pai ou mãe contribui com 1 parte;
  • os dois primeiros filhos contribuem com 1/2 parte cada um;
  • os filhos seguintes contribuem com uma parte cada:

O número de cotas é, portanto:

  • nbParts = 1 + nbEnfants * 0,5 + (nbEnfants - 2) * 0,5 se o empregado não for casado;
  • nbParts = 2 + nbEnfants * 0,5 + (nbEnfants - 2) * 0,5 se ele for casado;
    • onde nbEnfants é o número de filhos;
  • calcula-se a renda tributável R = 0,9 * S, onde S é o salário anual;
  • calcula-se o quociente familiar QF = R / nbParts;
  • calcula-se 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 possui 3 campos: champ1, champ2, champ3. Para calcular o imposto I, procura-se a primeira linha em que QF ≤ campo1 e utilizam-se os valores dessa linha. Por exemplo, para um funcionário casado, com dois filhos e um salário anual S de 50.000 euros:

Renda tributável: R = 0,9 * S = 45.000

Número de cotas: 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 – 1.394,96*nbParts=[0,14*45000-1394,96*3]=2.115. O imposto é arredondado para o euro inferior.

Se a relação QF <= campo1 for verdadeira já na primeira linha, então o imposto é nulo.

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

    0    0.45    20163.45

o que resulta no imposto bruto I = 0,45 * R – 20.163,45 * nbParts.

8.1.2. Limite máximo do quociente familiar

Image

Para saber se o limite máximo do quociente familiar QF se aplica, refaz-se o cálculo do imposto bruto sem os filhos. Ainda para o trabalhador casado com dois filhos e um salário anual S de 50.000 euros:

Renda tributável: R = 0,9 * S = 45.000

Número de faixas: nbParts = 2 (os filhos não são mais 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 – 1.394,96*nbParts = [0,14*45000-1394,96*2] = 3.510.

Ganho máximo relacionado aos filhos: 1551 * 2 = 3102 euros

Imposto mínimo: 3.510 – 3.102 = 408 euros

O imposto bruto com 3 faixas, já calculado em 2.115 euros, é superior ao imposto mínimo de 408 euros; portanto, o teto familiar não se aplica neste caso.

De modo geral, o imposto bruto é maior que (imposto1, imposto2), onde:

  • [impôt1]: é o imposto bruto calculado com os filhos;
  • [impôt2]: é o imposto bruto calculado sem os filhos e deduzido do ganho máximo (aqui, 1.551 euros por meia-parte) relacionado aos filhos;

8.1.3. Cálculo da redução

Image

Ainda para o trabalhador casado com dois filhos e um salário anual S de 50.000 euros:

O imposto bruto (2.115) resultante da etapa anterior é inferior a 2.627 euros para um casal (1.595 euros para um solteiro): portanto, a redução se aplica. Ela é obtida com o seguinte cálculo:

abatimento = limite (casal = 1.970 / solteiro = 1.196) – 0,75 * Imposto bruto

desconto = 1970 - 0,75 * 2115 = 383,75, arredondado para 384 euros.

Novo imposto bruto = 2.115 – 384 = 1.731 euros

8.1.4. Cálculo da redução de impostos

Image

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

  • solteiro: 21.037 euros;
  • casal: 42.074 euros; (o valor 37.968 utilizado no exemplo acima parece estar incorreto);

Esse limite é aumentado pelo valor: 3.797 * (número de meias-partes trazidas pelos filhos).

Ainda no caso do trabalhador casado com dois filhos e um salário anual S de 50.000 euros:

  • seu rendimento tributável (45.000 euros) é inferior ao limite (42.074 + 2 × 3.797) = 49.668 euros;
  • portanto, ele tem direito a uma redução de 20% do 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

Nosso cálculo termina aqui: o imposto líquido a pagar será de 1.384 euros. Na prática, o contribuinte pode se beneficiar de outras reduções, notadamente por doações a instituições de interesse público ou geral.

8.1.6. Caso dos rendimentos elevados

Nosso exemplo anterior corresponde à maioria dos casos de assalariados. No entanto, o cálculo do imposto é diferente no caso de rendas elevadas.

8.1.6.1. Limite máximo da redução de 10% sobre a renda anual

Na maioria dos casos, a renda tributável é obtida pela fórmula: R = 0,9 * S, em que S é o salário anual. Isso é chamado de redução de 10%. Essa redução tem um limite máximo. Em 2019:

  • ela não pode ser superior a 12.502 euros;
  • não pode ser inferior a 437 euros;

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

  • a redução de 10% é de 20.000 euros > 12.502 euros. Portanto, ela é reduzida para 12.502 euros;

8.1.6.2. Limite máximo do quociente familiar

Consideremos um caso em que se aplica o limite máximo familiar apresentado no parágrafo |Limite máximo do quociente familiar|. Tomemos o caso de um casal com três filhos e renda anual de 100.000 euros. Repassemos as etapas 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 partes;
  • seu quociente familiar é, portanto, QF = R / nbParts = 90.000 / 4 = 22.500 euros;
  • seu imposto bruto I1 com filhos é I1=0,14*90.000-1.394,96*4= 7.020 euros;
  • 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 teto do quociente familiar estabelece que o ganho proporcionado pelos filhos não pode exceder (1.551 × 4 meias-partes) = 6.204 euros. No entanto, neste caso, ele é I2-I1 = 15.404 – 7.020 = 8.384 euros, portanto, superior a 6.204 euros;
  • o imposto bruto é, portanto, recalculado como I3 = I2-6204 = 15.404 – 6.204 = 9.200 euros;

Esse casal não terá abatimento nem redução, e seu imposto final será de 9.200 euros.

8.1.7. Números oficiais

O cálculo do imposto é complexo. Ao longo do documento, os testes serão realizados com os exemplos a seguir. Os resultados são os do simulador da administração tributária |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 renda anual de 55.555 euros
Imposto = 2.815 euros
Alíquota de imposto = 14%
Imposto = 2.814 euros
Alíquota de imposto = 14 %
Casal com 2 filhos e renda anual de 50.000 euros
Imposto = 1.385 euros
Abatimento = 720 euros
Redução = 0 euros
Alíquota de imposto = 14%
Imposto = 1.384 euros
Abatimento = 384 euros
Redução = 347 euros
Alíquota de imposto = 14%
Casal com 3 filhos e renda anual de 50.000 euros
Imposto = 0 euro
Abatimento = 384 euros
Redução = 346 euros
Alíquota de imposto = 14%
Imposto = 0 euro
desconto = 720 euros
Redução = 0 euro
Alíquota de imposto = 14%
Solteiro, com 2 filhos e renda anual de 100.000 euros
Imposto = 19.884 euros
Abatimento = 0 euros
Redução = 0 euro
Alíquota de imposto = 41%
Imposto = 19.884 euros
Sobretaxa = 4.480 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Solteiro, com 3 filhos e renda anual de 100.000 euros
Imposto = 16.782 euros
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Imposto = 16.782 euros
Sobretaxa = 7.176 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Casal com 3 filhos e renda anual de 100.000 euros
Imposto = 9.200 euros
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 30%
Imposto = 9.200 euros
Sobretaxa = 2.180 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 30%
Casal com 5 filhos e renda anual de 100.000 euros
Imposto = 4.230 euros
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 14%
Imposto = 4.230 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 14%
Solteiro, sem filhos e com renda anual de 100.000 euros
Imposto = 22.986 euros
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Imposto = 22.986 euros
Sobretaxa = 0 euro
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Casal com 2 filhos e renda anual de 30.000 euros
Imposto = 0 euro
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 0%
Imposto = 0 euro
Desconto = 0 euro
Redução = 0 euro
Alíquota de imposto = 0 %
Solteiro, sem filhos e com renda anual de 200.000 euros
Imposto = 64.211 euros
Abatimento = 0 euro
Redução = 0 euros
Alíquota de imposto = 45%
Imposto = 64.210 euros
Sobretaxa = 7.498 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 45%
Casal com 3 filhos e renda anual de 200.000 euros
Imposto = 42.843 euros
Abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%
Imposto = 42.842 euros
Sobretaxa = 17.283 euros
abatimento = 0 euro
Redução = 0 euro
Alíquota de imposto = 41%

No exemplo acima, denomina-se “sobretaxa” o valor adicional que os rendimentos mais elevados pagam devido a dois fatores:

  • o teto de 10% para a dedução sobre a renda anual;
  • o limite máximo do quociente familiar;

Esse indicador não pôde ser verificado, pois o simulador da administração tributária não o fornece.

Percebe-se que o algoritmo do documento calcula o imposto correto em todas as ocasiões, embora com uma margem de erro de 1 euro. Essa margem de erro decorre dos arredondamentos. Todos os valores monetários são arredondados, ora para o euro superior, ora para o euro inferior. Como eu não conhecia as regras oficiais, os valores monetários do algoritmo do documento foram arredondados:

  • para o euro superior no caso de descontos e reduções;
  • para o euro inferior, no caso das sobretaxas e do imposto final;

Vamos desenvolver várias versões do aplicativo de cálculo do imposto.

8.2. Versão 1

Image

8.2.1. O script principal

Apresentamos um primeiro programa em que:

  • os dados necessários para o cálculo do imposto estão codificados diretamente no código na forma de listas e constantes;
  • os dados dos contribuintes (casado, filhos, salário) estão em um primeiro arquivo de texto [taxpayersdata.txt];
  • os resultados do cálculo do imposto (casado, filhos, salário, imposto) são armazenados em um segundo arquivo de texto [résultats.txt];

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


# módulos
import sys

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

# main -----------------------

# constantes
# arquivo de contribuintes
DATA = "./data/taxpayersdata.txt"
# arquivo de resultados
RESULTATS = "./data/résultats.txt"

try:
    # leitura dos dados dos contribuintes
    tax_payers = get_taxpayers_data(DATA)
    # lista de resultados
    results = []
    # cálculo do imposto dos contribuintes
    for tax_payer in tax_payers:
        # o cálculo do imposto retorna um dicionário de chaves
        # ['marié', 'enfants', 'salaire', 'impôt', 'surcôte', 'décôte', 'réduction', 'taux']
        result = calcul_impôt(tax_payer['marié'], tax_payer['enfants'], tax_payer['salaire'])
        # o dicionário é adicionado à lista de resultados
        results.append(result)
    # os resultados são gravados
    record_results(RESULTATS, results)
except BaseException as erreur:
    # podem ocorrer diversos erros: arquivo ausente, conteúdo incorreto do arquivo
    # o erro é exibido e o aplicativo é encerrado
    print(f"l'erreur suivante s'est produite : {erreur}]\n")
    sys.exit()

Notas

  • linha 4: utiliza-se o módulo [impots.v01.modules.impôts_module_01]. Vale lembrar que esse caminho é medido a partir da raiz do projeto PyCharm;
  • linha 10: o arquivo [data/taxpayersdata.txt] é o seguinte:
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 um tuplo de três elementos [marié / pacsé ou pas, nombre d'enfants, salaire annuel en euros].

  • linha 12: o arquivo onde serão colocados os resultados do cálculo do imposto para cada um dos contribuintes do arquivo [taxpayersdata.txt]. Ele 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: recuperam-se os dados dos contribuintes contidos em [taxpayersdata.txt]. Recupera-se uma lista de dicionários de chaves [marié, enfants, salaire], sendo que cada dicionário representa um contribuinte;
  • linhas 17-25: calcula-se o imposto dos contribuintes da lista [taxPayers]. Recupera-se uma lista [results], cujo cada elemento é, novamente, um dicionário de chaves [marié, enfants, salaire, impôt, surcôte, décôte, réduction, taux];
  • linha 27: a lista [results] dos resultados é gravada no arquivo [résultats.txt] no formato mostrado acima;
  • linhas 28-32: todas as exceções que possam ocorrer no módulo [impots.v01.modules.impôts_module_01] são interceptadas;

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

  • [get_taxpayers_data]: para ler os dados dos contribuintes;
  • [calcul_impôt]: para calcular o imposto desses contribuintes;
  • [record_results]: para gravar os resultados em um arquivo de texto;

Todas essas funções estão 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 do imposto foram reunidas no módulo [impots.v01.shared.impôts_module_01]:

Image

  • no [1]: definição das constantes para o cálculo do imposto;
  • no [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:


# importações
import codecs


# leitura dos dados dos contribuintes
# ----------------------------------------
def get_taxpayers_data(taxpayers_filename: str) -> list:
    # leitura dos dados dos contribuintes
    file = None
    try:
        # lista de contribuintes
        taxpayers = []
        # abertura do arquivo
        file = codecs.open(taxpayers_filename, "r", "utf8")
        # leitura da primeira linha do arquivo dos contribuintes
        ligne = file.readline().strip()
        # enquanto houver uma linha a ser processada
        while ligne != '':
            # recuperam-se os três campos “casado”, “filhos” e “salário” que compõem a linha
            (marié, enfants, salaire) = ligne.split(",")
            # eles são adicionados à lista de contribuintes
            taxpayers.append({'marié': marié.strip().lower(), 'enfants': int(enfants), 'salaire': int(salaire)})
            # lê-se uma nova linha do arquivo de contribuintes
            ligne = file.readline().strip()
        # retornamos o resultado
        return taxpayers
    finally:
        # fecha-se o arquivo, caso ele tenha sido aberto
        if file:
            file.close()

Notas

  • linha 7: [taxpayers_filename] é o nome do arquivo a ser processado. A função retorna uma lista;
  • linhas 18-24: o ciclo de processamento das linhas [marié, enfants, salaire] do arquivo de texto;
  • linha 20: os três elementos da linha são recuperados. Supõe-se aqui que a linha esteja sintaticamente correta, ou seja, que contenha os três elementos esperados;
  • linha 22: constrói-se um dicionário com as chaves [marié, enfants, salaire] e esse dicionário é adicionado à lista [taxPayers];
  • linha 26: uma vez processado o arquivo, retorna-se a lista [taxPayers];
  • linhas 10-30: observe-se que não foi inserida a cláusula [catch] no [try] da linha 10. A cláusula [catch] não é obrigatória. Na linha 27, foi inserida uma cláusula [finally] para fechar o arquivo de texto em todos os casos, haja ou não erro;
  • essa estrutura try/finally permite que uma eventual exceção escape (não há catch). Essa exceção será encaminhada para o script principal [main], que será interrompido e exibirá a exceção (ver parágrafo |O script principal|). Esse 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:


# importações
import codecs
import math

# faixas de imposto de 2019
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]

# constantes para o cálculo do imposto de 2019
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


# cálculo do imposto
# ----------------------------------------
def calcul_impôt(marié: str, enfants: int, salaire: int) -> dict:
    # casado: sim, não
    # filhos: número de filhos
    # salário: salário anual
    # limites, coeffr, coeffn: tabelas de dados que permitem o cálculo do imposto
    #
    # cálculo do imposto com filhos
    result1 = calcul_impôt_2(marié, enfants, salaire)
    impot1 = result1["impôt"]
    # cálculo do imposto sem filhos
    if enfants != 0:
        result2 = calcul_impôt_2(marié, 0, salaire)
        impot2 = result2["impôt"]
        # aplicação do teto do quociente familiar
        if enfants < 3:
            # PLAFOND_QF_DEMI_PART euros para os dois primeiros filhos
            impot2 = impot2 - enfants * PLAFOND_QF_DEMI_PART
        else:
            # PLAFOND_QF_DEMI_PART euros para os dois primeiros filhos, o dobro para os seguintes
            impot2 = impot2 - 2 * PLAFOND_QF_DEMI_PART - (enfants - 2) * 2 * PLAFOND_QF_DEMI_PART
    else:
        impot2 = impot1
        result2 = result1

    # considera-se o imposto mais alto, com a alíquota e a sobretaxa correspondentes
    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"]

    # cálculo de uma eventual redução
    décôte = get_décôte(marié, salaire, impot)
    impot -= décôte
    # cálculo de uma eventual redução de impostos
    réduction = get_réduction(marié, salaire, enfants, impot)
    impot -= réduction
    # resultado
    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: as faixas de imposto (ver parágrafo |Cálculo do imposto bruto|);
  • linhas 11-20: as constantes do cálculo do imposto;
  • vale ressaltar que os elementos inicializados nas linhas 5 a 20 serão globais para as funções que descreveremos. Portanto, eles são conhecidos, desde que a função que os utiliza não declare variáveis com os mesmos nomes;
  • os valores das linhas 5-20 mudam a cada ano. Aqui, são os valores de 2019;
  • linha 25: a função [calcul_impôt] recebe três parâmetros:
    • [marié]: sim/não, indica se o contribuinte é casado ou vive em união estável;
    • [enfants]: o número de filhos;
    • [salaire]: seu salário anual em euros;
  • linhas 31-33: cálculo do imposto levando em conta os filhos;
  • linhas 34-47: essas linhas implementam o limite máximo do quociente familiar (ver parágrafo |Limite máximo do quociente familiar|);
  • linhas 49-57: essas linhas calculam a alíquota de imposto do contribuinte, bem como uma eventual sobretaxa (ver parágrafo |Casos de rendas elevadas|);
  • linhas 59-61: cálculo de uma eventual redução (ver parágrafo |Cálculo da redução|);
  • linhas 62-64: cálculo de uma eventual redução do imposto a pagar (cf. parágrafo |Cálculo da redução do imposto|);

O algoritmo é bastante complexo e não o detalharemos além do que dizem os comentários. O algoritmo implementa o modo de cálculo do imposto, conforme descrito no parágrafo |O problema|.

8.2.5. A função [calcul_impôt_2]

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


def calcul_impôt_2(marié: str, enfants: int, salaire: int) -> list:
    # casado: sim, não
    # filhos: número de filhos
    # salário: salário anual
    # limites, coeffr, coeffn: as tabelas de dados que permitem o cálculo do imposto
    #
    # número de faixas
    marié = marié.strip().lower()
    if marié == "oui":
        nb_parts = enfants / 2 + 2
    else:
        nb_parts = enfants / 2 + 1

    # 1 parcela por filho a partir do terceiro
    if enfants >= 3:
        # meia parcela adicional para cada filho a partir do terceiro
        nb_parts += 0.5 * (enfants - 2)

    # renda tributável
    revenu_imposable = get_revenu_imposable(salaire)
    # sobretaxa
    surcôte = math.floor(revenu_imposable - 0.9 * salaire)
    # para problemas de arredondamento
    if surcôte < 0:
        surcôte = 0

    # quociente familiar
    quotient = revenu_imposable / nb_parts
    # é colocado no final da tabela de limites para encerrar o ciclo a seguir
    limites[len(limites) - 1] = quotient
    # cálculo do imposto
    i = 0
    while quotient > limites[i]:
        i += 1
        # como o quociente familiar foi colocado no final da tabela de limites, o loop anterior
    # não pode ultrapassar a tabela de limites

    # agora é possível calcular o imposto
    impôt = math.floor(revenu_imposable * coeffr[i] - nb_parts * coeffn[i])
    # resultado
    return {"impôt": impôt, "surcôte": surcôte, "taux": coeffr[i]}

Esse algoritmo foi descrito no parágrafo 8.1.1.

8.2.6. A função [get_décôte]

A função [get_décôte] implementa o cálculo do eventual desconto do imposto (parágrafo |Cálculo do desconto|):


# calcula uma eventual redução
def get_décôte(marié: str, salaire: int, impots: int) -> int:
    # inicialmente, um desconto nulo
    décôte = 0
    # valor máximo do imposto para ter direito ao abatimento
    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:
        # valor máximo da redução
        plafond_décôte = PLAFOND_DECOTE_COUPLE if marié == "oui" else PLAFOND_DECOTE_CELIBATAIRE
        # abatimento teórico
        décôte = plafond_décôte - 0.75 * impots
        # a redução não pode exceder o valor do imposto
        if décôte > impots:
            décôte = impots

        # não há desconto <0
        if décôte < 0:
            décôte = 0

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

8.2.7. A função [get_réduction]

A função [get_réduction] implementa o cálculo da eventual redução do imposto a pagar (parágrafo |Cálculo da redução de impostos|):


# calcula uma eventual redução
def get_réduction(marié: str, salaire: int, enfants: int, impots: int) -> int:
    # o teto de renda para ter direito à redução de 20%
    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

    # renda tributável
    revenu_imposable = get_revenu_imposable(salaire)
    # redução
    réduction = 0
    if revenu_imposable < plafond_revenu_pour_réduction:
        # redução de 20%
        réduction = 0.2 * impots

    # resultado
    return math.ceil(réduction)

8.2.8. A função [get_revenu_imposable]

A função [get_revenu_imposable] calcula a renda tributável a partir do salário anual:


# revenu_imposable = salaireAnnuel - dedução
# a dedução tem um valor mínimo e um valor máximo
# ----------------------------------------
def get_revenu_imposable(salaire: int) -> int:
    # abatimento de 10% do salário
    abattement = 0.1 * salaire
    # essa dedução não pode exceder ABATTEMENT_DIXPOURCENT_MAX
    if abattement > ABATTEMENT_DIXPOURCENT_MAX:
        abattement = ABATTEMENT_DIXPOURCENT_MAX

    # a dedução não pode ser inferior a ABATTEMENT_DIXPOURCENT_MIN
    if abattement < ABATTEMENT_DIXPOURCENT_MIN:
        abattement = ABATTEMENT_DIXPOURCENT_MIN

    # renda tributável
    revenu_imposable = salaire - abattement
    # resultado
    return math.floor(revenu_imposable)

8.2.9. A função [record_results]

A função [record_results] grava os resultados do cálculo do imposto em um arquivo de texto:


# gravação dos resultados em um arquivo de texto
# ----------------------------------------
def record_results(results_filename: str, results: list):
    # results_filename: o nome do arquivo de texto onde os resultados serão gravados
    # results: a lista de resultados na forma de uma lista de dicionários
    # cada dicionário é gravado em uma linha de texto
    résultats = None
    try:
        # abertura do arquivo de resultados
        résultats = codecs.open(results_filename, "w", "utf8")
        # análise dos contribuintes
        for result in results:
            # o resultado é registrado no arquivo de resultados
            résultats.write(f"{result}\n")
            # próximo contribuinte
    finally:
        # fecha-se o arquivo, caso tenha sido aberto
        if résultats:
            résultats.close()

8.2.10. Os resultados

Como já foi mencionado, com o arquivo de contribuintes [taxpayersdata.txt] a seguir:

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 arquivo [résultats.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}

Esses resultados estão de acordo com os números oficiais do parágrafo |Números oficiais|.

Agora, vamos executar essa versão em uma 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 já conhecido: aquele em que um módulo não é encontrado, neste caso, o módulo [impots]. Vale lembrar que isso significa que:

  • o interpretador Python percorreu, uma a uma, as pastas do Python Path;
  • em nenhuma delas, ele encontrou uma pasta que contivesse um script [impots.py];

A versão [v02] trará uma solução para esse problema.