"""Calculadora de IRPJ e CSLL (Lucro Real e Lucro Presumido).""" from __future__ import annotations from dataclasses import dataclass, field from decimal import Decimal from typing import Optional from src.calculators import ResultadoCalculo, arred from src.fiscal.constants import ( ALIQ_CSLL_FINANCEIRAS, ALIQ_CSLL_PADRAO, ALIQ_IRPJ_ADICIONAL, ALIQ_IRPJ_BASE, LIMITE_ADICIONAL_IRPJ_TRIMESTRAL, PERCENTUAL_PRESUMIDO_CSLL, PERCENTUAL_PRESUMIDO_IRPJ, ) from src.fiscal.entities import RegimeTributario @dataclass class ResultadoIRPJ: lucro_real_ajustado: Decimal = Decimal("0") base_calculo: Decimal = Decimal("0") aliquota_base: Decimal = Decimal("15") valor_base: Decimal = Decimal("0") base_adicional: Decimal = Decimal("0") valor_adicional: Decimal = Decimal("0") valor_irpj_total: Decimal = Decimal("0") # Incentivos e deduções incentivos_fiscais: Decimal = Decimal("0") irpj_a_recolher: Decimal = Decimal("0") compensacoes: Decimal = Decimal("0") detalhes: dict = field(default_factory=dict) @dataclass class ResultadoCSLL: base_calculo: Decimal = Decimal("0") aliquota: Decimal = Decimal("0") valor_csll: Decimal = Decimal("0") csll_a_recolher: Decimal = Decimal("0") compensacoes: Decimal = Decimal("0") detalhes: dict = field(default_factory=dict) def calcular_irpj_lucro_real( lucro_antes_ir: Decimal, adicoes: Decimal = Decimal("0"), exclusoes: Decimal = Decimal("0"), compensacoes_prejuizo: Decimal = Decimal("0"), incentivos_fiscais: Decimal = Decimal("0"), irpj_estimativas: Decimal = Decimal("0"), periodo: str = "trimestral", ) -> ResultadoIRPJ: r = ResultadoIRPJ() lucro_ajustado = arred(lucro_antes_ir + adicoes - exclusoes) r.lucro_real_ajustado = lucro_ajustado # Compensação de prejuízo (limite 30% do lucro ajustado) limite_compensacao = arred(lucro_ajustado * Decimal("0.30")) comp_efetiva = min(compensacoes_prejuizo, limite_compensacao) r.base_calculo = max(Decimal("0"), arred(lucro_ajustado - comp_efetiva)) r.aliquota_base = ALIQ_IRPJ_BASE r.valor_base = arred(r.base_calculo * ALIQ_IRPJ_BASE / 100) limite_adicional = ( LIMITE_ADICIONAL_IRPJ_TRIMESTRAL if periodo == "trimestral" else arred(LIMITE_ADICIONAL_IRPJ_TRIMESTRAL * Decimal("4")) ) r.base_adicional = max(Decimal("0"), arred(r.base_calculo - limite_adicional)) r.valor_adicional = arred(r.base_adicional * ALIQ_IRPJ_ADICIONAL / 100) r.valor_irpj_total = arred(r.valor_base + r.valor_adicional) r.incentivos_fiscais = arred(incentivos_fiscais) r.irpj_a_recolher = max( Decimal("0"), arred(r.valor_irpj_total - r.incentivos_fiscais - irpj_estimativas), ) r.detalhes = { "adicoes": adicoes, "exclusoes": exclusoes, "compensacao_prejuizo_utilizada": comp_efetiva, "compensacoes_disponiveis": compensacoes_prejuizo, "limite_compensacao_30pct": limite_compensacao, "estimativas_pagas": irpj_estimativas, } return r def calcular_irpj_lucro_presumido( receita_bruta: Decimal, outras_receitas: Decimal = Decimal("0"), atividade: str = "venda_mercadorias", incentivos_fiscais: Decimal = Decimal("0"), irpj_anteriores: Decimal = Decimal("0"), ) -> ResultadoIRPJ: r = ResultadoIRPJ() percentual = PERCENTUAL_PRESUMIDO_IRPJ.get(atividade, Decimal("8.0")) lucro_presumido = arred(receita_bruta * percentual / 100) r.lucro_real_ajustado = arred(lucro_presumido + outras_receitas) r.base_calculo = r.lucro_real_ajustado r.aliquota_base = ALIQ_IRPJ_BASE r.valor_base = arred(r.base_calculo * ALIQ_IRPJ_BASE / 100) r.base_adicional = max(Decimal("0"), arred(r.base_calculo - LIMITE_ADICIONAL_IRPJ_TRIMESTRAL)) r.valor_adicional = arred(r.base_adicional * ALIQ_IRPJ_ADICIONAL / 100) r.valor_irpj_total = arred(r.valor_base + r.valor_adicional) r.incentivos_fiscais = incentivos_fiscais r.irpj_a_recolher = max( Decimal("0"), arred(r.valor_irpj_total - incentivos_fiscais - irpj_anteriores), ) r.detalhes = { "receita_bruta": receita_bruta, "percentual_presuncao": percentual, "lucro_presumido": lucro_presumido, "outras_receitas": outras_receitas, "atividade": atividade, } return r def calcular_csll_lucro_real( lucro_antes_csll: Decimal, adicoes: Decimal = Decimal("0"), exclusoes: Decimal = Decimal("0"), compensacoes_base_negativa: Decimal = Decimal("0"), tipo_empresa: str = "padrao", csll_estimativas: Decimal = Decimal("0"), ) -> ResultadoCSLL: r = ResultadoCSLL() base_ajustada = arred(lucro_antes_csll + adicoes - exclusoes) limite_comp = arred(base_ajustada * Decimal("0.30")) comp_efetiva = min(compensacoes_base_negativa, limite_comp) r.base_calculo = max(Decimal("0"), arred(base_ajustada - comp_efetiva)) aliq = ALIQ_CSLL_FINANCEIRAS if tipo_empresa == "financeira" else ALIQ_CSLL_PADRAO r.aliquota = aliq r.valor_csll = arred(r.base_calculo * aliq / 100) r.csll_a_recolher = max(Decimal("0"), arred(r.valor_csll - csll_estimativas)) r.detalhes = { "adicoes": adicoes, "exclusoes": exclusoes, "compensacao_utilizada": comp_efetiva, "estimativas_pagas": csll_estimativas, } return r def calcular_csll_lucro_presumido( receita_bruta: Decimal, outras_receitas: Decimal = Decimal("0"), atividade: str = "comercio_industria", tipo_empresa: str = "padrao", csll_anteriores: Decimal = Decimal("0"), ) -> ResultadoCSLL: r = ResultadoCSLL() percentual = PERCENTUAL_PRESUMIDO_CSLL.get(atividade, Decimal("12.0")) base_presumida = arred(receita_bruta * percentual / 100 + outras_receitas) r.base_calculo = base_presumida aliq = ALIQ_CSLL_FINANCEIRAS if tipo_empresa == "financeira" else ALIQ_CSLL_PADRAO r.aliquota = aliq r.valor_csll = arred(r.base_calculo * aliq / 100) r.csll_a_recolher = max(Decimal("0"), arred(r.valor_csll - csll_anteriores)) r.detalhes = { "receita_bruta": receita_bruta, "percentual_presuncao": percentual, "base_presumida_bruta": base_presumida, "outras_receitas": outras_receitas, "atividade": atividade, } return r def calcular_irpj_estimativa_mensal( receita_bruta_mes: Decimal, atividade: str = "venda_mercadorias", outras_receitas: Decimal = Decimal("0"), ) -> dict[str, Decimal]: """Cálculo de IRPJ por estimativa mensal (Lucro Real).""" percentual = PERCENTUAL_PRESUMIDO_IRPJ.get(atividade, Decimal("8.0")) base = arred(receita_bruta_mes * percentual / 100 + outras_receitas) # Adicional: excedente ao limite mensal de R$20.000 limite_mensal = Decimal("20000") irpj_base = arred(base * ALIQ_IRPJ_BASE / 100) adicional = arred(max(Decimal("0"), base - limite_mensal) * ALIQ_IRPJ_ADICIONAL / 100) return { "base_estimada": base, "irpj_aliquota_base": irpj_base, "irpj_adicional": adicional, "total_estimativa": arred(irpj_base + adicional), }