| """Calculadora de ISS (Imposto sobre Serviços).""" |
| from __future__ import annotations |
|
|
| from dataclasses import dataclass |
| from decimal import Decimal |
| from typing import Optional |
|
|
| from src.calculators import ResultadoCalculo, arred |
| from src.fiscal.constants import ALIQ_ISS_MAXIMA, ALIQ_ISS_MINIMA, ALIQ_ISS_SERVICOS |
|
|
|
|
| @dataclass |
| class ParametrosISS: |
| valor_servico: Decimal |
| codigo_servico: str |
| aliquota_municipal: Optional[Decimal] = None |
| retencao_fonte: bool = False |
| municipio_prestacao: str = "" |
| municipio_tomador: str = "" |
| responsavel_retencao: str = "prestador" |
|
|
| def aliquota_efetiva(self) -> Decimal: |
| if self.aliquota_municipal is not None: |
| aliq = self.aliquota_municipal |
| aliq = max(aliq, ALIQ_ISS_MINIMA) |
| aliq = min(aliq, ALIQ_ISS_MAXIMA) |
| return aliq |
| return ALIQ_ISS_SERVICOS.get( |
| self.codigo_servico[:2], ALIQ_ISS_MAXIMA |
| ) |
|
|
|
|
| def calcular_iss(p: ParametrosISS) -> ResultadoCalculo: |
| aliq = p.aliquota_efetiva() |
| valor = arred(p.valor_servico * aliq / 100) |
|
|
| return ResultadoCalculo( |
| base_calculo=p.valor_servico, |
| aliquota=aliq, |
| valor_tributo=valor, |
| valor_a_recolher=valor, |
| detalhes={ |
| "codigo_servico": p.codigo_servico, |
| "retencao_fonte": p.retencao_fonte, |
| "municipio_prestacao": p.municipio_prestacao, |
| "responsavel": "tomador" if p.retencao_fonte else "prestador", |
| }, |
| ) |
|
|
|
|
| def calcular_iss_retido_tomador( |
| valor_servico: Decimal, |
| codigo_servico: str, |
| aliquota_municipal: Optional[Decimal] = None, |
| ) -> Decimal: |
| p = ParametrosISS( |
| valor_servico=valor_servico, |
| codigo_servico=codigo_servico, |
| aliquota_municipal=aliquota_municipal, |
| retencao_fonte=True, |
| ) |
| resultado = calcular_iss(p) |
| return resultado.valor_tributo |
|
|
|
|
| |
| SERVICOS_RETENCAO_OBRIGATORIA = { |
| "01", |
| "02", |
| "03", |
| "04", |
| "07", |
| "08", |
| "10", |
| "11", |
| "13", |
| "15", |
| "16", |
| "17", |
| "20", |
| "21", |
| } |
|
|
|
|
| def requer_retencao_iss(codigo_servico: str) -> bool: |
| return codigo_servico[:2] in SERVICOS_RETENCAO_OBRIGATORIA |
|
|
|
|
| def calcular_iss_simples_nacional( |
| receita_bruta_acumulada_12m: Decimal, |
| receita_servicos_mes: Decimal, |
| anexo: str = "III", |
| ) -> dict[str, Decimal]: |
| """Cálculo do ISS dentro do Simples Nacional por anexo.""" |
| |
| tabelas = { |
| "III": [ |
| (Decimal("180000"), Decimal("6.0"), Decimal("0")), |
| (Decimal("360000"), Decimal("11.2"), Decimal("9360")), |
| (Decimal("720000"), Decimal("13.5"), Decimal("17640")), |
| (Decimal("1800000"), Decimal("16.0"), Decimal("35640")), |
| (Decimal("3600000"), Decimal("21.0"), Decimal("125640")), |
| (Decimal("4800000"), Decimal("33.0"), Decimal("648000")), |
| ], |
| "IV": [ |
| (Decimal("180000"), Decimal("4.5"), Decimal("0")), |
| (Decimal("360000"), Decimal("9.0"), Decimal("8100")), |
| (Decimal("720000"), Decimal("10.2"), Decimal("12420")), |
| (Decimal("1800000"), Decimal("14.0"), Decimal("39780")), |
| (Decimal("3600000"), Decimal("22.0"), Decimal("183780")), |
| (Decimal("4800000"), Decimal("33.0"), Decimal("828000")), |
| ], |
| "V": [ |
| (Decimal("180000"), Decimal("15.5"), Decimal("0")), |
| (Decimal("360000"), Decimal("18.0"), Decimal("4500")), |
| (Decimal("720000"), Decimal("19.5"), Decimal("9900")), |
| (Decimal("1800000"), Decimal("20.5"), Decimal("17100")), |
| (Decimal("3600000"), Decimal("23.0"), Decimal("62100")), |
| (Decimal("4800000"), Decimal("30.5"), Decimal("540000")), |
| ], |
| } |
|
|
| tabela = tabelas.get(anexo, tabelas["III"]) |
| aliq_nominal = Decimal("6.0") |
| deducao = Decimal("0") |
|
|
| for limite, aliq, ded in tabela: |
| if receita_bruta_acumulada_12m <= limite: |
| aliq_nominal = aliq |
| deducao = ded |
| break |
|
|
| aliq_efetiva = ( |
| arred((receita_bruta_acumulada_12m * aliq_nominal / 100 - deducao) / receita_bruta_acumulada_12m * 100) |
| if receita_bruta_acumulada_12m > 0 |
| else Decimal("0") |
| ) |
|
|
| |
| percentual_iss_das = { |
| "III": Decimal("33.50"), |
| "IV": Decimal("0"), |
| "V": Decimal("33.50"), |
| } |
|
|
| valor_das = arred(receita_servicos_mes * aliq_efetiva / 100) |
| valor_iss = arred(valor_das * percentual_iss_das.get(anexo, Decimal("33.5")) / 100) |
|
|
| return { |
| "receita_bruta_12m": receita_bruta_acumulada_12m, |
| "aliq_nominal": aliq_nominal, |
| "deducao": deducao, |
| "aliq_efetiva": aliq_efetiva, |
| "valor_das_total": valor_das, |
| "valor_iss_estimado": valor_iss, |
| "anexo": anexo, |
| } |
|
|