Speed / src /calculators /iss.py
LesterCerioli's picture
Building Speed LLM
d9d7b41
Raw
History Blame Contribute Delete
5.79 kB
"""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
# Serviços sujeitos a retenção obrigatória pelo tomador (LC 116/2003, Art. 6º)
SERVICOS_RETENCAO_OBRIGATORIA = {
"01", # Serviços de informática e congêneres
"02", # Pesquisa e desenvolvimento
"03", # Serviços prestados mediante locação de bens
"04", # Saúde, assistência médica
"07", # Engenharia, arquitetura, agronomia, agrimensura
"08", # Pesquisa, vigilância, rastreamento, monitoramento
"10", # Serviços de intermediação e congêneres
"11", # Guarda, estacionamento, armazenamento
"13", # Fonografia, fotografia, cinematografia, reprografia
"15", # Serviços bancários ou financeiros
"16", # Serviços de transporte de natureza municipal
"17", # Serviços de apoio técnico, administrativo, jurídico
"20", # Serviços portuários, aeroportuários
"21", # Serviços de registros públicos, cartorários
}
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 simplificadas Simples Nacional (Lei Complementar 123/2006)
tabelas = {
"III": [ # Serviços em geral (Anexo 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": [ # Serviços especializados (Anexo IV) - sem CPP
(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": [ # Serviços com fator R (Anexo 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")
)
# ISS representa ~7-10% do DAS no Anexo III/IV
percentual_iss_das = {
"III": Decimal("33.50"),
"IV": Decimal("0"), # ISS pago separado no Anexo IV
"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,
}