from __future__ import annotations from dataclasses import dataclass, field from datetime import date from decimal import Decimal from typing import Optional from src.calculators import ResultadoCalculo, arred # --------------------------------------------------------------------------- # Tabelas do Simples Nacional (LC 123/2006 com alterações da LC 155/2016) # Vigência: a partir de 01/01/2018 # Faixas: (limite_acumulado_12m, aliq_nominal, deducao) # --------------------------------------------------------------------------- TABELA_SIMPLES: dict[str, list[tuple[Decimal, Decimal, Decimal]]] = { "I": [ # Comércio (Decimal("180000.00"), Decimal("4.00"), Decimal("0.00")), (Decimal("360000.00"), Decimal("7.30"), Decimal("5940.00")), (Decimal("720000.00"), Decimal("9.50"), Decimal("13860.00")), (Decimal("1800000.00"), Decimal("10.70"), Decimal("22500.00")), (Decimal("3600000.00"), Decimal("14.30"), Decimal("87300.00")), (Decimal("4800000.00"), Decimal("19.00"), Decimal("378000.00")), ], "II": [ # Indústria (Decimal("180000.00"), Decimal("4.50"), Decimal("0.00")), (Decimal("360000.00"), Decimal("7.80"), Decimal("5940.00")), (Decimal("720000.00"), Decimal("10.00"), Decimal("13860.00")), (Decimal("1800000.00"), Decimal("11.20"), Decimal("22500.00")), (Decimal("3600000.00"), Decimal("14.70"), Decimal("85500.00")), (Decimal("4800000.00"), Decimal("30.00"), Decimal("720000.00")), ], "III": [ # Serviços (com CPP) (Decimal("180000.00"), Decimal("6.00"), Decimal("0.00")), (Decimal("360000.00"), Decimal("11.20"), Decimal("9360.00")), (Decimal("720000.00"), Decimal("13.50"), Decimal("17640.00")), (Decimal("1800000.00"), Decimal("16.00"), Decimal("35640.00")), (Decimal("3600000.00"), Decimal("21.00"), Decimal("125640.00")), (Decimal("4800000.00"), Decimal("33.00"), Decimal("648000.00")), ], "IV": [ # Serviços (sem CPP — INSS pago separado) (Decimal("180000.00"), Decimal("4.50"), Decimal("0.00")), (Decimal("360000.00"), Decimal("9.00"), Decimal("8100.00")), (Decimal("720000.00"), Decimal("10.20"), Decimal("12420.00")), (Decimal("1800000.00"), Decimal("14.00"), Decimal("39780.00")), (Decimal("3600000.00"), Decimal("22.00"), Decimal("183780.00")), (Decimal("4800000.00"), Decimal("33.00"), Decimal("828000.00")), ], "V": [ # Serviços com fator R (profissões regulamentadas) (Decimal("180000.00"), Decimal("15.50"), Decimal("0.00")), (Decimal("360000.00"), Decimal("18.00"), Decimal("4500.00")), (Decimal("720000.00"), Decimal("19.50"), Decimal("9900.00")), (Decimal("1800000.00"), Decimal("20.50"), Decimal("17100.00")), (Decimal("3600000.00"), Decimal("23.00"), Decimal("62100.00")), (Decimal("4800000.00"), Decimal("30.50"), Decimal("540000.00")), ], } PARTILHA_DAS: dict[str, list[dict[str, Decimal]]] = { "I": [ {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.74"), "PIS": Decimal("2.76"), "CPP": Decimal("41.50"), "ICMS": Decimal("34.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.74"), "PIS": Decimal("2.76"), "CPP": Decimal("41.50"), "ICMS": Decimal("34.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.74"), "PIS": Decimal("2.76"), "CPP": Decimal("42.00"), "ICMS": Decimal("33.50")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.74"), "PIS": Decimal("2.76"), "CPP": Decimal("42.00"), "ICMS": Decimal("33.50")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.74"), "PIS": Decimal("2.76"), "CPP": Decimal("42.00"), "ICMS": Decimal("33.50")}, {"IRPJ": Decimal("13.5"), "CSLL": Decimal("10.0"), "COFINS": Decimal("28.27"), "PIS": Decimal("6.13"), "CPP": Decimal("42.10"), "ICMS": Decimal("0.00")}, ], "II": [ {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("11.51"), "PIS": Decimal("2.49"), "CPP": Decimal("37.50"), "IPI": Decimal("7.50"), "ICMS": Decimal("32.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("11.51"), "PIS": Decimal("2.49"), "CPP": Decimal("37.50"), "IPI": Decimal("7.50"), "ICMS": Decimal("32.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("11.51"), "PIS": Decimal("2.49"), "CPP": Decimal("37.50"), "IPI": Decimal("7.50"), "ICMS": Decimal("32.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("11.51"), "PIS": Decimal("2.49"), "CPP": Decimal("37.50"), "IPI": Decimal("7.50"), "ICMS": Decimal("32.00")}, {"IRPJ": Decimal("5.5"), "CSLL": Decimal("3.5"), "COFINS": Decimal("11.51"), "PIS": Decimal("2.49"), "CPP": Decimal("37.50"), "IPI": Decimal("7.50"), "ICMS": Decimal("32.00")}, {"IRPJ": Decimal("8.0"), "CSLL": Decimal("7.5"), "COFINS": Decimal("20.96"), "PIS": Decimal("4.54"), "CPP": Decimal("23.50"), "IPI": Decimal("35.50"), "ICMS": Decimal("0.00")}, ], "III": [ {"IRPJ": Decimal("4.0"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.82"), "PIS": Decimal("2.78"), "CPP": Decimal("43.40"), "ISS": Decimal("33.50")}, {"IRPJ": Decimal("4.0"), "CSLL": Decimal("3.5"), "COFINS": Decimal("14.05"), "PIS": Decimal("3.05"), "CPP": Decimal("43.40"), "ISS": Decimal("32.00")}, {"IRPJ": Decimal("4.0"), "CSLL": Decimal("3.5"), "COFINS": Decimal("13.64"), "PIS": Decimal("2.96"), "CPP": Decimal("43.40"), "ISS": Decimal("32.50")}, {"IRPJ": Decimal("4.0"), "CSLL": Decimal("3.5"), "COFINS": Decimal("13.64"), "PIS": Decimal("2.96"), "CPP": Decimal("43.40"), "ISS": Decimal("32.50")}, {"IRPJ": Decimal("4.0"), "CSLL": Decimal("3.5"), "COFINS": Decimal("12.82"), "PIS": Decimal("2.78"), "CPP": Decimal("43.40"), "ISS": Decimal("33.50")}, {"IRPJ": Decimal("35.0"), "CSLL": Decimal("15.0"), "COFINS": Decimal("16.03"), "PIS": Decimal("3.47"), "CPP": Decimal("30.50"), "ISS": Decimal("0.00")}, ], "IV": [ {"IRPJ": Decimal("18.8"), "CSLL": Decimal("15.2"), "COFINS": Decimal("17.67"), "PIS": Decimal("3.83"), "ISS": Decimal("44.50")}, {"IRPJ": Decimal("19.8"), "CSLL": Decimal("15.2"), "COFINS": Decimal("20.55"), "PIS": Decimal("4.45"), "ISS": Decimal("40.00")}, {"IRPJ": Decimal("20.8"), "CSLL": Decimal("15.2"), "COFINS": Decimal("19.73"), "PIS": Decimal("4.27"), "ISS": Decimal("40.00")}, {"IRPJ": Decimal("17.8"), "CSLL": Decimal("19.2"), "COFINS": Decimal("18.90"), "PIS": Decimal("4.10"), "ISS": Decimal("40.00")}, {"IRPJ": Decimal("18.8"), "CSLL": Decimal("19.2"), "COFINS": Decimal("18.08"), "PIS": Decimal("3.92"), "ISS": Decimal("40.00")}, {"IRPJ": Decimal("53.5"), "CSLL": Decimal("21.5"), "COFINS": Decimal("20.55"), "PIS": Decimal("4.45"), "ISS": Decimal("0.00")}, ], } LIMITE_SIMPLES = Decimal("4800000.00") LIMITE_MEI = Decimal("81000.00") @dataclass class ResultadoSimples: receita_bruta_mes: Decimal receita_bruta_acumulada_12m: Decimal anexo: str faixa: int aliq_nominal: Decimal deducao: Decimal aliq_efetiva: Decimal valor_das: Decimal partilha: dict[str, Decimal] = field(default_factory=dict) periodo: str = "" dentro_limite: bool = True def _calcular_aliq_efetiva( rec_12m: Decimal, aliq_nominal: Decimal, deducao: Decimal, ) -> Decimal: if rec_12m <= 0: return Decimal("0") return arred(((rec_12m * aliq_nominal / 100) - deducao) / rec_12m * 100, 6) def _obter_faixa(rec_12m: Decimal, tabela: list) -> tuple[int, Decimal, Decimal]: """Retorna (índice_faixa, aliq_nominal, deducao).""" for i, (limite, aliq, ded) in enumerate(tabela): if rec_12m <= limite: return i, aliq, ded return len(tabela) - 1, tabela[-1][1], tabela[-1][2] def calcular_das( receita_bruta_mes: Decimal, receita_bruta_acumulada_12m: Decimal, anexo: str = "I", periodo: str = "", ) -> ResultadoSimples: """ Calcula o DAS (Documento de Arrecadação do Simples Nacional) mensal. Args: receita_bruta_mes: Receita bruta do mês de referência receita_bruta_acumulada_12m: Soma dos últimos 12 meses (ou desde o início) anexo: "I", "II", "III", "IV" ou "V" periodo: "YYYY-MM" """ dentro_limite = receita_bruta_acumulada_12m <= LIMITE_SIMPLES tabela = TABELA_SIMPLES.get(anexo, TABELA_SIMPLES["I"]) faixa_idx, aliq_nominal, deducao = _obter_faixa(receita_bruta_acumulada_12m, tabela) aliq_efetiva = _calcular_aliq_efetiva(receita_bruta_acumulada_12m, aliq_nominal, deducao) valor_das = arred(receita_bruta_mes * aliq_efetiva / 100) partilha_tabela = PARTILHA_DAS.get(anexo, []) partilha: dict[str, Decimal] = {} if partilha_tabela and faixa_idx < len(partilha_tabela): perc_faixa = partilha_tabela[faixa_idx] for tributo, perc in perc_faixa.items(): partilha[tributo] = arred(valor_das * perc / 100) return ResultadoSimples( receita_bruta_mes=receita_bruta_mes, receita_bruta_acumulada_12m=receita_bruta_acumulada_12m, anexo=anexo, faixa=faixa_idx + 1, aliq_nominal=aliq_nominal, deducao=deducao, aliq_efetiva=aliq_efetiva, valor_das=valor_das, partilha=partilha, periodo=periodo, dentro_limite=dentro_limite, ) def calcular_fator_r( folha_12m: Decimal, rec_12m: Decimal, ) -> Decimal: """ Fator R: relação folha de pagamento / receita bruta nos últimos 12 meses. Se Fator R >= 28%, o contribuinte pode optar pelo Anexo III ao invés do V. """ if rec_12m <= 0: return Decimal("0") return arred(folha_12m / rec_12m * 100, 4) def determinar_anexo_servicos( fator_r: Decimal, lista_servico: str, ) -> str: """ Determina o anexo aplicável para empresas de serviços. Serviços do Anexo V com Fator R >= 28% podem usar o Anexo III. """ anexo_iv = { "construcao_civil", "servicos_vigilancia", "limpeza", "transporte_cargas", "cuidados_pessoais", } anexo_iii = { "agencia_viagens", "academias", "agronegocio", "arquitetura_engenharia_simples", } fator_r_atividades = { "medicina", "odontologia", "psicologia", "fisioterapia", "advocacia", "contabilidade", "consultoria", "ti_software", "engenharia", "arquitetura", } if lista_servico in anexo_iv: return "IV" if lista_servico in anexo_iii: return "III" if lista_servico in fator_r_atividades: return "III" if fator_r >= Decimal("28") else "V" return "III" @dataclass class ResultadoPGDAS: """Resultado do PGDAS-D mensal.""" cnpj: str periodo: str receita_bruta_total: Decimal das_total: Decimal das_por_estabelecimento: list[ResultadoSimples] = field(default_factory=list) data_vencimento: Optional[date] = None @property def resumo_partilha(self) -> dict[str, Decimal]: totais: dict[str, Decimal] = {} for r in self.das_por_estabelecimento: for tributo, valor in r.partilha.items(): totais[tributo] = totais.get(tributo, Decimal("0")) + valor return totais def calcular_pgdas( cnpj: str, periodo: str, receitas_por_atividade: list[dict], receita_acumulada_12m: Decimal, ) -> ResultadoPGDAS: """ Calcula o PGDAS-D completo para um período. Args: cnpj: CNPJ da empresa periodo: "YYYY-MM" receitas_por_atividade: [{"valor": ..., "anexo": "I/II/III/IV/V"}] receita_acumulada_12m: Receita dos últimos 12 meses """ das_total = Decimal("0") resultados = [] for ativ in receitas_por_atividade: valor = Decimal(str(ativ.get("valor", 0))) anexo = ativ.get("anexo", "I") resultado = calcular_das(valor, receita_acumulada_12m, anexo, periodo) das_total += resultado.valor_das resultados.append(resultado) ano, mes = map(int, periodo.split("-")) mes_vcto = mes + 1 if mes < 12 else 1 ano_vcto = ano if mes < 12 else ano + 1 vcto = date(ano_vcto, mes_vcto, 20) return ResultadoPGDAS( cnpj=cnpj, periodo=periodo, receita_bruta_total=sum(Decimal(str(a["valor"])) for a in receitas_por_atividade), das_total=arred(das_total), das_por_estabelecimento=resultados, data_vencimento=vcto, ) MEI_VALORES_FIXOS = { "comercio_industria": Decimal("70.60"), # R$ 70,60/mês (2024) "servicos": Decimal("79.60"), "comercio_servicos": Decimal("80.60"), }