"""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, }