"""Cálculo do custo de contratação — regime Empregado CLT. Fórmulas portadas 1:1 da planilha de referência do escritório (`projects/planilha de custo/1972 - CUSTO EMPREGADO SALÁRIO.xlsx`), com duas correções deliberadas e explicitamente pedidas pelo usuário: 1. A planilha original nunca soma a dedução por dependente à base do IRRF quando usa o desconto real de INSS (só quando usa o desconto simplificado — onde a dedução por dependente não se aplica por lei, já que os dois métodos são mutuamente exclusivos). Aqui, quando o desconto real de INSS é o escolhido, a dedução por dependente também é subtraída da base do IRRF. 2. A partir de janeiro/2026, a Lei nº 15.270/2025 (art. 3º-A da Lei nº 9.250/1995) passou a reduzir o IRRF já calculado pela tabela progressiva tradicional — ver `_reducao_lei_15270` abaixo. Essa lei não mudou a tabela progressiva em si, só acrescenta essa redução por cima. Os parâmetros fiscais (faixas de INSS/IRRF, dedução por dependente, os coeficientes da Lei 15.270/2025 etc.) não são mais constantes deste módulo — mudam todo ano, então vêm de fora via `ParametrosFiscais` (montado a partir de `ParametroFiscalCustoContratacao`, editável pela própria tela; ver `portal_api/models.py`). `tabelas.py` continua existindo só como o seed/default dessa configuração. """ from dataclasses import dataclass @dataclass class ParametrosFiscais: faixas_inss: list[tuple[float, float, float]] teto_desconto_inss: float faixas_irrf: list[tuple[float, float, float]] aliquota_irrf_topo: float deduzir_irrf_topo: float desconto_simplificado_irrf: float deducao_por_dependente: float reducao_lei_15270_coeficiente_a: float reducao_lei_15270_coeficiente_b: float reducao_lei_15270_limite: float @dataclass class EntradaSimulacaoEmpregado: nome_referencia: str empresa: str cargo: str salario_contratual: float adicional_art62: float comissao: float dsr: float outros_itens_remuneracao: list[tuple[str, float]] # somam à base de INSS/FGTS/13º/férias/IRRF, como salário percentual_inss_empregador: float # fração, ex.: 0.26 percentual_fgts: float # fração, ex.: 0.08 dependentes: int vale_transporte: float seguro_vida: float vale_alimentacao: float assiduidade: float fundo_formacao: float outros_beneficios: list[tuple[str, float]] # custo variável do empregador, cada item some no PDF desconto_vale_transporte: float desconto_vale_alimentacao: float desconto_sindicato: float outros_descontos: list[tuple[str, float]] # descontado direto do líquido do empregado @dataclass class ResultadoSimulacaoEmpregado: entrada: EntradaSimulacaoEmpregado inss_salario: float fgts_salario: float decimo_terceiro_avo: float inss_decimo_terceiro: float fgts_decimo_terceiro: float ferias_avo: float ferias_um_terco: float inss_ferias: float fgts_ferias: float multa_40_fgts: float subtotal_custos_fixos: float subtotal_custos_variaveis: float custo_total_empresa: float base_inss_empregado: float aliquota_inss_empregado: float desconto_inss_empregado: float base_irrf: float aliquota_irrf: float desconto_irrf_tabela: float reducao_lei_15270: float desconto_irrf: float liquido_empregado: float def _desconto_inss(base: float, parametros: ParametrosFiscais) -> tuple[float, float]: """(alíquota, desconto) do INSS do empregado — progressivo, com teto fixo.""" for limite, aliquota, deduzir in parametros.faixas_inss: if base <= limite: return aliquota, (base * aliquota) - deduzir return 0.0, parametros.teto_desconto_inss def _desconto_irrf_tabela(base: float, parametros: ParametrosFiscais) -> tuple[float, float]: """(alíquota, desconto) do IRRF pela tabela progressiva tradicional; desconto zerado se <= R$10 (regra de dispensa de retenção pra valores muito baixos, já presente na planilha original).""" aliquota, deduzir = parametros.aliquota_irrf_topo, parametros.deduzir_irrf_topo for limite, faixa_aliquota, faixa_deduzir in parametros.faixas_irrf: if base <= limite: aliquota, deduzir = faixa_aliquota, faixa_deduzir break desconto_bruto = (base * aliquota) - deduzir return aliquota, desconto_bruto if desconto_bruto > 10 else 0.0 def _reducao_lei_15270(rendimento_bruto_mensal: float, parametros: ParametrosFiscais) -> float: """Redução adicional de IRRF da Lei nº 15.270/2025 — isenção total até R$5.000,00 de rendimento bruto mensal, decrescente até zerar em `reducao_lei_15270_limite` (R$7.350,00 na regra vigente). Aplicada sobre o rendimento bruto (antes do INSS), não sobre a base já líquida de INSS.""" if rendimento_bruto_mensal >= parametros.reducao_lei_15270_limite: return 0.0 reducao = parametros.reducao_lei_15270_coeficiente_a - ( parametros.reducao_lei_15270_coeficiente_b * rendimento_bruto_mensal ) return max(0.0, reducao) def calcula_custo_empregado( entrada: EntradaSimulacaoEmpregado, parametros: ParametrosFiscais ) -> ResultadoSimulacaoEmpregado: perc_inss = entrada.percentual_inss_empregador perc_fgts = entrada.percentual_fgts base_remuneracao = ( entrada.salario_contratual + entrada.adicional_art62 + entrada.comissao + entrada.dsr + sum(valor for _, valor in entrada.outros_itens_remuneracao) ) inss_salario = base_remuneracao * perc_inss fgts_salario = base_remuneracao * perc_fgts decimo_terceiro_avo = base_remuneracao / 12 inss_decimo_terceiro = decimo_terceiro_avo * perc_inss fgts_decimo_terceiro = decimo_terceiro_avo * perc_fgts ferias_avo = base_remuneracao / 12 ferias_um_terco = ferias_avo / 3 inss_ferias = (ferias_avo + ferias_um_terco) * perc_inss fgts_ferias = (ferias_avo + ferias_um_terco) * perc_fgts multa_40_fgts = (fgts_salario + fgts_ferias + fgts_decimo_terceiro) * 0.4 subtotal_custos_fixos = ( base_remuneracao + inss_salario + fgts_salario + decimo_terceiro_avo + inss_decimo_terceiro + fgts_decimo_terceiro + ferias_avo + ferias_um_terco + inss_ferias + fgts_ferias + multa_40_fgts ) subtotal_custos_variaveis = ( entrada.vale_transporte + entrada.seguro_vida + entrada.vale_alimentacao + entrada.assiduidade + entrada.fundo_formacao + sum(valor for _, valor in entrada.outros_beneficios) ) custo_total_empresa = subtotal_custos_fixos + subtotal_custos_variaveis base_inss_empregado = base_remuneracao aliquota_inss_empregado, desconto_inss_empregado = _desconto_inss(base_inss_empregado, parametros) if desconto_inss_empregado >= parametros.desconto_simplificado_irrf: base_irrf = ( base_inss_empregado - desconto_inss_empregado - (entrada.dependentes * parametros.deducao_por_dependente) ) else: base_irrf = base_inss_empregado - parametros.desconto_simplificado_irrf aliquota_irrf, desconto_irrf_tabela = _desconto_irrf_tabela(base_irrf, parametros) reducao_lei_15270 = _reducao_lei_15270(base_remuneracao, parametros) desconto_irrf = max(0.0, desconto_irrf_tabela - reducao_lei_15270) total_descontos_diversos = ( entrada.desconto_vale_transporte + entrada.desconto_vale_alimentacao + entrada.desconto_sindicato + sum(valor for _, valor in entrada.outros_descontos) ) liquido_empregado = base_remuneracao - desconto_inss_empregado - desconto_irrf - total_descontos_diversos return ResultadoSimulacaoEmpregado( entrada=entrada, inss_salario=inss_salario, fgts_salario=fgts_salario, decimo_terceiro_avo=decimo_terceiro_avo, inss_decimo_terceiro=inss_decimo_terceiro, fgts_decimo_terceiro=fgts_decimo_terceiro, ferias_avo=ferias_avo, ferias_um_terco=ferias_um_terco, inss_ferias=inss_ferias, fgts_ferias=fgts_ferias, multa_40_fgts=multa_40_fgts, subtotal_custos_fixos=subtotal_custos_fixos, subtotal_custos_variaveis=subtotal_custos_variaveis, custo_total_empresa=custo_total_empresa, base_inss_empregado=base_inss_empregado, aliquota_inss_empregado=aliquota_inss_empregado, desconto_inss_empregado=desconto_inss_empregado, base_irrf=base_irrf, aliquota_irrf=aliquota_irrf, desconto_irrf_tabela=desconto_irrf_tabela, reducao_lei_15270=reducao_lei_15270, desconto_irrf=desconto_irrf, liquido_empregado=liquido_empregado, ) def formata_moeda(valor: float) -> str: """8500.0 -> 'R$ 8.500,00'; -12.3 -> '-R$ 12,30'.""" negativo = valor < 0 inteiro, decimal = f"{abs(valor):,.2f}".split(".") texto = f"R$ {inteiro.replace(',', '.')},{decimal}" return f"-{texto}" if negativo else texto def formata_percentual(fracao: float) -> str: """0.26 -> '26,00%'.""" return f"{fracao * 100:.2f}".replace(".", ",") + "%"