Speed / src /generators /efd_contribuicoes.py
LesterCerioli's picture
Building Speed LLM
d9d7b41
Raw
History Blame Contribute Delete
9.06 kB
from __future__ import annotations
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
from pathlib import Path
from typing import Optional
from src.calculators.pis_cofins import (
CreditoPisCofins,
ReceitaBruta,
ResultadoPisCofins,
calcular_pis_cofins,
)
from src.fiscal.entities import Empresa, NotaFiscal, PeriodoApuracao, RegimeTributario
from src.generators.sped_writer import ArquivoSPED, criar_registro
VERSAO_LEIAUTE = "006"
@dataclass
class ConfigEFDContrib:
versao: str = VERSAO_LEIAUTE
finalidade: str = "0"
ind_situacao_especial: str = ""
class GeradorEFDContribuicoes:
def __init__(
self,
periodo: PeriodoApuracao,
creditos: Optional[list[CreditoPisCofins]] = None,
cfg: Optional[ConfigEFDContrib] = None,
):
self.periodo = periodo
self.creditos = creditos or []
self.cfg = cfg or ConfigEFDContrib()
self._arquivo = ArquivoSPED(
f"EFD_CONTRIB_{periodo.empresa.cnpj}_{periodo.data_inicio.strftime('%Y%m')}.txt"
)
def _bloco_0(self) -> None:
emp = self.periodo.empresa
end = emp.endereco
self._arquivo.adicionar_linha_raw(criar_registro(
"0000",
self.cfg.versao,
self.cfg.finalidade,
self.periodo.data_inicio,
self.periodo.data_fim,
emp.razao_social,
emp.cnpj,
emp.cnpj[:8], # cod_atividade (raiz CNPJ simplificado)
emp.ie,
emp.im,
emp.suframa,
self.cfg.ind_situacao_especial,
emp.regime_tributario.value,
emp.endereco.uf.value,
))
self._arquivo.adicionar_linha_raw(criar_registro("0001", "0"))
ind_metodo_apropriacao = "1" # 1=Método de Apropriação Direta
if emp.regime_tributario == RegimeTributario.LUCRO_REAL:
cod_inc_trib = "1" # Lucro Real
elif emp.regime_tributario == RegimeTributario.LUCRO_PRESUMIDO:
cod_inc_trib = "2" # Lucro Presumido
else:
cod_inc_trib = "3" # Imunes/Isentas
self._arquivo.adicionar_linha_raw(criar_registro(
"0110",
cod_inc_trib,
ind_metodo_apropriacao,
"1", # cod_cred_pis_cofins_nao_aprop
))
self._arquivo.adicionar_linha_raw(criar_registro(
"0140",
emp.cnpj,
emp.nome_fantasia or emp.razao_social,
end.uf.value,
emp.ie,
end.cod_municipio,
emp.im,
emp.suframa,
))
self._arquivo.adicionar_linha_raw(criar_registro(
"0990", self._arquivo.total_linhas() + 1
))
def _bloco_c(self) -> None:
self._arquivo.adicionar_linha_raw(criar_registro("C001", "0"))
for nf in self.periodo.notas_saida:
tipo_oper = "1" # Saída
self._arquivo.adicionar_linha_raw(criar_registro(
"C100",
tipo_oper,
"0", # ind_emit (0=emissão própria)
nf.destinatario.cnpj,
nf.modelo,
nf.serie,
nf.numero,
nf.chave_acesso,
nf.data_emissao,
nf.data_saida_entrada,
nf.valor_produtos,
Decimal("0"), # vl_desc
nf.valor_ipi,
nf.valor_total,
))
for item in nf.itens:
self._arquivo.adicionar_linha_raw(criar_registro(
"C170",
item.numero_item,
item.produto.codigo,
item.produto.descricao,
item.quantidade,
item.produto.unidade,
item.valor_unitario,
item.desconto,
item.cfop,
item.produto.cst_pis,
Decimal("0"), # vl_bc_pis
Decimal("0"), # aliq_pis
Decimal("0"), # quant_bc_pis
Decimal("0"), # aliq_pis_quant
Decimal("0"), # vl_pis
item.produto.cst_cofins,
Decimal("0"), # vl_bc_cofins
Decimal("0"), # aliq_cofins
Decimal("0"), # quant_bc_cofins
Decimal("0"), # aliq_cofins_quant
Decimal("0"), # vl_cofins
"", # cod_cta
))
self._arquivo.adicionar_linha_raw(criar_registro(
"C990", self._arquivo.total_linhas()
))
def _bloco_m(self, resultado: ResultadoPisCofins) -> None:
self._arquivo.adicionar_linha_raw(criar_registro("M001", "0"))
self._arquivo.adicionar_linha_raw(criar_registro(
"M100",
"01", # cod_cred_aprop
"1", # ind_cred_ori (1=apurado no período)
resultado.base_pis, # vl_bc_pis
resultado.aliq_pis, # aliq_pis_aplic
Decimal("0"), # quant_bc_pis
Decimal("0"), # aliq_pis_quant
resultado.creditos_pis, # vl_cred
Decimal("0"), # vl_ajustes_a_cred
resultado.creditos_pis, # vl_cred_dif
Decimal("0"), # vl_cred_disp
resultado.creditos_pis, # vl_cred_desc_pa_ant
Decimal("0"), # vl_cred_per_pa_ant
Decimal("0"), # vl_cred_dcomp_pa_ant
resultado.creditos_pis, # vl_saldo_cred_retornar
))
self._arquivo.adicionar_linha_raw(criar_registro(
"M200",
resultado.valor_pis_debito, # vl_tot_cont_nc_per
Decimal("0"), # vl_tot_cred_desc
Decimal("0"), # vl_tot_cred_desc_ant
resultado.creditos_pis, # vl_tot_cred_desc_per
resultado.pis_a_recolher, # vl_tot_cont_nc_dev
Decimal("0"), # vl_ret_nc
resultado.pis_a_recolher, # vl_out_ded_nc
resultado.pis_a_recolher, # vl_cont_nc_rec
Decimal("0"), # vl_tot_cont_cum_per
Decimal("0"), # vl_ret_cum
Decimal("0"), # vl_out_ded_cum
Decimal("0"), # vl_cont_cum_rec
resultado.pis_a_recolher, # vl_tot_cont_rec
))
self._arquivo.adicionar_linha_raw(criar_registro(
"M600",
resultado.valor_cofins_debito, # vl_tot_cont_nc_per
Decimal("0"), # vl_tot_cred_desc
Decimal("0"), # vl_tot_cred_desc_ant
resultado.creditos_cofins, # vl_tot_cred_desc_per
resultado.cofins_a_recolher, # vl_tot_cont_nc_dev
Decimal("0"), # vl_ret_nc
resultado.cofins_a_recolher, # vl_out_ded_nc
resultado.cofins_a_recolher, # vl_cont_nc_rec
Decimal("0"), # vl_tot_cont_cum_per
Decimal("0"), # vl_ret_cum
Decimal("0"), # vl_out_ded_cum
Decimal("0"), # vl_cont_cum_rec
resultado.cofins_a_recolher, # vl_tot_cont_rec
))
self._arquivo.adicionar_linha_raw(criar_registro(
"M990", self._arquivo.total_linhas()
))
def _bloco_1(self) -> None:
self._arquivo.adicionar_linha_raw(criar_registro("1001", "1"))
self._arquivo.adicionar_linha_raw(criar_registro(
"1990", self._arquivo.total_linhas()
))
def _bloco_9(self) -> None:
self._arquivo.adicionar_linha_raw(criar_registro("9001", "0"))
qt = self._arquivo.total_linhas() + 3
self._arquivo.adicionar_linha_raw(criar_registro("9900", "0000", "1"))
self._arquivo.adicionar_linha_raw(criar_registro("9990", qt))
self._arquivo.adicionar_linha_raw(criar_registro("9999", qt + 1))
def gerar(self, diretorio: str | Path = ".") -> Path:
receitas = [
ReceitaBruta(
descricao=f"Vendas NF {nf.numero}",
valor=nf.valor_produtos,
cst_pis="01",
cst_cofins="01",
)
for nf in self.periodo.notas_saida
]
resultado = calcular_pis_cofins(
receitas=receitas,
regime=self.periodo.empresa.regime_tributario,
creditos=self.creditos,
)
self._bloco_0()
self._bloco_c()
self._bloco_m(resultado)
self._bloco_1()
self._bloco_9()
return self._arquivo.salvar(diretorio)