"""Testes dos geradores de arquivos SPED e XML fiscal.""" import pytest import re from datetime import date from decimal import Decimal from pathlib import Path from src.fiscal.entities import ( Contato, Empresa, Endereco, ItemNotaFiscal, LancamentoContabil, NotaFiscal, PeriodoApuracao, Produto, RegimeTributario, TipoEmpresa, UF, ) from src.generators.sped_writer import ArquivoSPED, RegistroSPED, criar_registro from src.generators.efd_icms_ipi import GeradorEFDICMSIPI from src.generators.efd_contribuicoes import GeradorEFDContribuicoes from src.generators.ecd import GeradorECD, PlanoContas from src.generators.ecf import DadosLucroPresumido, DadosLucroReal, GeradorECF from src.generators.nfe_xml import GeradorNFeXML from src.generators.efd_reinf import ( EventoR2010, GeradorEFDReinf, PrestadorServico, ) from src.generators.esocial import ( GeradorESocial, Trabalhador, VinculoEmpregaticio, FolhaPagamento, ItemFolha, RUBRICAS_PADRAO, ) from src.generators.dctf import DebitoDCTF, GeradorDCTF, ItemDCTF, montar_dctf_do_periodo from src.generators.cte import GeradorCTe, CargaCTe, ParteCTe, DadosTransporte, DocumentoReferenciado from src.generators.nfce_xml import GeradorNFCeXML, ConsumidorNFCe from src.generators.mdfe import GeradorMDFe, MunicipioDescarga, DocumentoMDFe, ConductorMDFe, SeguroMDFe from src.generators.dirf import GeradorDIRF, BeneficiarioDIRF, ResponsavelDIRF from src.generators.defis import GeradorDEFIS, ReceitaMensalDEFIS, SocioDEFIS from src.generators.destda import GeradorDeSTDA, OperacaoSTDeSTDA from src.generators.gia import GeradorGIA, ApuracaoGIA, ApuracaoGIAST # --------------------------------------------------------------------------- # Fixtures # --------------------------------------------------------------------------- @pytest.fixture def empresa_sp(): return Empresa( cnpj="11222333000181", razao_social="EMPRESA TESTE LTDA", nome_fantasia="TESTE", ie="111111111111", regime_tributario=RegimeTributario.LUCRO_PRESUMIDO, tipo_empresa=TipoEmpresa.COMERCIO, endereco=Endereco( logradouro="Av. Paulista", numero="1000", bairro="Bela Vista", municipio="São Paulo", uf=UF.SP, cep="01310100", cod_municipio="3550308", ), contato=Contato(telefone="1133334444", email="teste@teste.com"), ) @pytest.fixture def cliente_sp(): return Empresa( cnpj="22333444000181", razao_social="CLIENTE TESTE SA", regime_tributario=RegimeTributario.LUCRO_PRESUMIDO, tipo_empresa=TipoEmpresa.COMERCIO, endereco=Endereco( logradouro="Rua das Flores", numero="100", bairro="Centro", municipio="Campinas", uf=UF.SP, cep="13010050", cod_municipio="3509502", ), ) @pytest.fixture def produto_padrao(): return Produto( codigo="PROD001", descricao="PRODUTO TESTE", ncm="84713012", unidade="UN", aliq_icms=Decimal("18"), aliq_ipi=Decimal("5"), cst_icms="000", cst_ipi="50", cst_pis="01", cst_cofins="01", ) @pytest.fixture def nota_fiscal(empresa_sp, cliente_sp, produto_padrao): item = ItemNotaFiscal( numero_item=1, produto=produto_padrao, cfop="5102", quantidade=Decimal("10"), valor_unitario=Decimal("100.00"), ) return NotaFiscal( numero="000001", serie="001", data_emissao=date(2024, 1, 15), data_saida_entrada=date(2024, 1, 15), emitente=empresa_sp, destinatario=cliente_sp, natureza_operacao="VENDA DE MERCADORIA", itens=[item], chave_acesso="35240111222333000181550010000000011000000015", ) @pytest.fixture def periodo(empresa_sp, nota_fiscal): return PeriodoApuracao( data_inicio=date(2024, 1, 1), data_fim=date(2024, 1, 31), empresa=empresa_sp, notas_saida=[nota_fiscal], ) # --------------------------------------------------------------------------- # Testes do escritor base SPED # --------------------------------------------------------------------------- class TestSpedWriter: def test_criar_registro_formato_pipe(self): linha = criar_registro("C100", "1", "0", "12345678") assert linha.startswith("|C100|") assert linha.endswith("|\n") def test_criar_registro_data(self): linha = criar_registro("0000", date(2024, 1, 1)) assert "01012024" in linha def test_criar_registro_decimal(self): linha = criar_registro("E110", Decimal("1234.56")) assert "1234,56" in linha def test_criar_registro_none_vazio(self): linha = criar_registro("X001", None, "") parts = linha.strip("|").split("|") assert parts[1] == "" assert parts[2] == "" def test_arquivo_sped_contagem_linhas(self): arq = ArquivoSPED("teste.txt") arq.adicionar_linha_raw(criar_registro("0000", "017")) arq.adicionar_linha_raw(criar_registro("0001", "0")) assert arq.total_linhas() == 2 def test_registro_sped_builder(self): reg = RegistroSPED("C100") reg.add("1").add("0").add("12345678000195") linha = reg.to_line() assert "|C100|1|0|12345678000195|" in linha # --------------------------------------------------------------------------- # Testes EFD ICMS/IPI # --------------------------------------------------------------------------- class TestEFDICMSIPI: def test_gera_arquivo_existente(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) assert caminho.exists() assert caminho.stat().st_size > 0 def test_registro_0000_presente(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) conteudo = caminho.read_text() assert "|0000|" in conteudo def test_cnpj_no_registro_0000(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) conteudo = caminho.read_text() assert "11222333000181" in conteudo def test_registro_c100_presente(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) conteudo = caminho.read_text() assert "|C100|" in conteudo def test_registro_e110_presente(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) conteudo = caminho.read_text() assert "|E110|" in conteudo def test_registro_9999_presente(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) conteudo = caminho.read_text() assert "|9999|" in conteudo def test_todas_linhas_sao_pipe_delimited(self, periodo, tmp_path): gerador = GeradorEFDICMSIPI(periodo) caminho = gerador.gerar(tmp_path) for linha in caminho.read_text().splitlines(): assert linha.startswith("|") and linha.endswith("|"), f"Linha inválida: {linha}" def test_nome_arquivo_correto(self, periodo): gerador = GeradorEFDICMSIPI(periodo) assert "11222333000181" in gerador._arquivo.nome_arquivo assert "202401" in gerador._arquivo.nome_arquivo # --------------------------------------------------------------------------- # Testes EFD Contribuições # --------------------------------------------------------------------------- class TestEFDContribuicoes: def test_gera_arquivo(self, periodo, tmp_path): gerador = GeradorEFDContribuicoes(periodo) caminho = gerador.gerar(tmp_path) assert caminho.exists() def test_registro_m200_presente(self, periodo, tmp_path): gerador = GeradorEFDContribuicoes(periodo) caminho = gerador.gerar(tmp_path) assert "|M200|" in caminho.read_text() def test_registro_m600_presente(self, periodo, tmp_path): gerador = GeradorEFDContribuicoes(periodo) caminho = gerador.gerar(tmp_path) assert "|M600|" in caminho.read_text() # --------------------------------------------------------------------------- # Testes ECD # --------------------------------------------------------------------------- class TestECD: def test_gera_arquivo(self, periodo, tmp_path): gerador = GeradorECD(periodo) caminho = gerador.gerar(tmp_path) assert caminho.exists() assert caminho.stat().st_size > 100 def test_plano_contas_no_arquivo(self, periodo, tmp_path): gerador = GeradorECD(periodo) caminho = gerador.gerar(tmp_path) assert "|I050|" in caminho.read_text() def test_registro_i001_presente(self, periodo, tmp_path): gerador = GeradorECD(periodo) caminho = gerador.gerar(tmp_path) assert "|I001|" in caminho.read_text() def test_lancamentos_contabeis(self, periodo, empresa_sp, tmp_path): periodo.lancamentos = [ LancamentoContabil( data=date(2024, 1, 5), numero_lancamento="000001", historico="Venda de mercadorias", debito_conta="1.1.2.01", credito_conta="4.1.01", valor=Decimal("1000.00"), ) ] gerador = GeradorECD(periodo) caminho = gerador.gerar(tmp_path) assert "|I200|" in caminho.read_text() assert "|I250|" in caminho.read_text() def test_plano_contas_customizado(self, periodo, tmp_path): plano = [ PlanoContas("1", "ATIVO", 1, "S", "D"), PlanoContas("1.01", "CAIXA", 2, "A", "D"), ] gerador = GeradorECD(periodo, plano_contas=plano) caminho = gerador.gerar(tmp_path) assert "CAIXA" in caminho.read_text() # --------------------------------------------------------------------------- # Testes ECF # --------------------------------------------------------------------------- class TestECF: def test_gera_ecf_lucro_presumido(self, empresa_sp, tmp_path): dados = DadosLucroPresumido( receita_venda_mercadorias=Decimal("500000"), receita_prestacao_servicos=Decimal("100000"), ) gerador = GeradorECF(empresa_sp, 2023, dados_lp=dados) caminho = gerador.gerar(tmp_path) assert caminho.exists() def test_registro_0000_ecf(self, empresa_sp, tmp_path): dados = DadosLucroPresumido(receita_venda_mercadorias=Decimal("100000")) gerador = GeradorECF(empresa_sp, 2023, dados_lp=dados) caminho = gerador.gerar(tmp_path) assert "|0000|" in caminho.read_text() def test_gera_ecf_lucro_real(self, tmp_path): empresa = Empresa( cnpj="11222333000181", razao_social="EMPRESA LR LTDA", regime_tributario=RegimeTributario.LUCRO_REAL, tipo_empresa=TipoEmpresa.COMERCIO, endereco=Endereco( logradouro="Rua X", numero="1", bairro="B", municipio="SP", uf=UF.SP, cep="01310100", ), ) dados = DadosLucroReal( lucro_contabil=Decimal("200000"), adicoes=Decimal("10000"), exclusoes=Decimal("5000"), ) gerador = GeradorECF(empresa, 2023, dados_lr=dados) caminho = gerador.gerar(tmp_path) assert "|L020|" in caminho.read_text() # --------------------------------------------------------------------------- # Testes NF-e XML # --------------------------------------------------------------------------- class TestNFeXML: def test_gera_xml_valido(self, nota_fiscal, tmp_path): gerador = GeradorNFeXML(nota_fiscal) xml = gerador.gerar_xml() assert xml.startswith("" in xml assert "" in xml or "" in xml def test_chave_acesso_44_digitos(self, nota_fiscal): gerador = GeradorNFeXML(nota_fiscal) chave = gerador._gerar_chave() assert len(chave) == 44 assert chave.isdigit() def test_salva_arquivo_xml(self, nota_fiscal, tmp_path): gerador = GeradorNFeXML(nota_fiscal) caminho = gerador.salvar(tmp_path) assert caminho.exists() assert caminho.suffix == ".xml" # --------------------------------------------------------------------------- # Testes EFD-Reinf # --------------------------------------------------------------------------- class TestEFDReinf: def test_gera_r2010(self): gerador = GeradorEFDReinf("11222333000181") evt = EventoR2010( cnpj_tomador="11222333000181", periodo="2024-01", prestadores=[ PrestadorServico( cnpj_cpf="22333444000181", nome="PRESTADOR TESTE", valor_bruto=Decimal("10000"), valor_bc_csll=Decimal("10000"), valor_bc_irrf=Decimal("10000"), valor_bc_pis=Decimal("10000"), valor_bc_cofins=Decimal("10000"), ) ], ) xml = gerador.gerar_r2010(evt) assert "evtServTom" in xml assert "22333444000181" in xml def test_gera_r2099(self): gerador = GeradorEFDReinf("11222333000181") xml = gerador.gerar_r2099("2024-01") assert "evtFechamento" in xml def test_salva_eventos(self, tmp_path): gerador = GeradorEFDReinf("11222333000181") arquivos = gerador.salvar_eventos(tmp_path, periodo="2024-01") assert len(arquivos) >= 2 assert all(a.exists() for a in arquivos) # --------------------------------------------------------------------------- # Testes e-Social # --------------------------------------------------------------------------- class TestESocial: def test_gera_s2200_admissao(self): gerador = GeradorESocial("11222333000181") trab = Trabalhador( cpf="12345678909", nome="JOAO DA SILVA", data_nascimento=date(1985, 3, 15), ) vinculo = VinculoEmpregaticio( trabalhador=trab, matricula="001", data_admissao=date(2024, 1, 2), salario_base=Decimal("3000"), ) xml = gerador.gerar_s2200(vinculo) assert "evtAdmissao" in xml assert "JOAO DA SILVA" in xml def test_gera_s1200_folha(self): gerador = GeradorESocial("11222333000181") trab = Trabalhador(cpf="12345678909", nome="MARIA SOUZA", data_nascimento=date(1990, 6, 20)) rubrica = RUBRICAS_PADRAO[0] folha = FolhaPagamento( trabalhador=trab, matricula="002", periodo="2024-01", itens=[ItemFolha(rubrica=rubrica, valor=Decimal("3000"))], base_cp=Decimal("3000"), base_fgts=Decimal("3000"), valor_fgts=Decimal("240"), ) xml = gerador.gerar_s1200(folha) assert "evtRemun" in xml assert "3000.00" in xml def test_gera_s1299_fechamento(self): gerador = GeradorESocial("11222333000181") xml = gerador.gerar_s1299("2024-01") assert "evtFechamento" in xml # --------------------------------------------------------------------------- # Testes DCTF # --------------------------------------------------------------------------- class TestDCTF: def test_gera_xml_dctf(self, empresa_sp, tmp_path): item = ItemDCTF(debito=DebitoDCTF( codigo_receita="2089", periodo_apuracao="2024-01", valor_debito=Decimal("5000"), )) gerador = GeradorDCTF(empresa_sp, "2024-01", [item]) xml = gerador.gerar_xml() assert "