Business - Automação Comercial

SIntegra: Abordagem Completa – Implementanto o Sintegra

Continuando a nossa série de artigos sobre o Sintegra, iremos agora abordar a implementação do arquivo propriamente dita.

por Victory Fernandes



No primeiro artigo da série, foram abordados os conceitos e características gerais do Sintegra, tendo sido apresentada a estrutura básica do arquivo e seus principais registros, incluindo o exemplo de montagem do registro 50 como forma de demonstrar a estruturação geral de um registro do sintegra.

Continuando a nossa série de artigos sobre o Sintegra, iremos agora abordar a implementação do arquivo propriamente dita. Através dos 2 demos que acompanham o artigo, é demonstrada a geração de todos os registros do sintegra, e a geração dos principais registros do sintegra descritos no artigo anterior a partir de dados contidos em um banco de dados Interbase 6.01 (Freeware).

Visão geral da Implementação

Como o Sintegra se baseia em uma série de informações fornecidas pelo usuário do sistema gerencial em questão, e como estas informações devem ser cuidadosamente tratadas antes de serem enviadas para o banco de dados do sistema e por fim utilizadas na geração do arquivo de texto, sob pena de recusa do arquivo gerado por parte do Programa Validador, foi desenvolvida a SIntegra32Dll.dll, como uma solução que visa facilitar e agilizar o processo de tratamento destas informações, uma vez que seus usuários podem abstrair a camada de geração dos registros e validação das informações, se preocupando apenas em fazer as chamadas à dll passando os parâmetros necessários para a criação do registro.

É importante lembrar que o arquivo do sintegra será gerado referente a um período anterior, com base em informações que já foram adicionadas a um banco de dados e que devem ser coerentes com o sintegra. Então, a Sintegra32dll.dll deve ser usada na verdade em dois momentos, a exemplo:

  • Momento A: Em um sistema de controle de notas fiscais com Sintegra, as entradas e saídas das notas devem ser feitas levando em consideração que o banco de dados gerado será usado para geração do arquivo magnético, assim, logo após o preenchimento de cada nota fiscal, o sistema deve antes de tudo chamar a dll para os registros correspondentes e testar se houve erro, salvando as informações no banco de dados, caso nenhum problema seja encontrado.

  • Momento B: No momento da geração do arquivo magnético propriamente dita, o sistema deve ler as informações do banco de dados e fazer as chamadas às funções da dll de acordo com o registros desejados.


Figura 01: Processo de Implementação do Sintegra

Na Figura 01 vemos os passos envolvidos na implementação do sintegra que são descritos a seguir. Os passos em vermelho são aqueles que devem ser implementados no sistema gerencial e os passos em verde podem ser abstraídos a partir da utilização da Sintegra32dll.dll.

1. Tabelas e Campos de acordo com o Sintegra: Todas as tabelas do sistema gerencial em questão devem estar formatadas de acordo com os campos dos registros do sintegra, observando-se tipos de campo (numérico ou alfanumérico) e tamanho máximo dos mesmos.

2. Telas de Cadastro de Dados do Sintegra: As telas do sistema gerencial devem estar de acordo com o banco de dados e, as necessidades do sintegra. Atenção principalmente para as telas de Vendas, Entrada de Nota Fiscal e Saída de Nota Fiscal que normalmente precisam ser revistas sendo necessário fazer pelo menos pequenas alterações não previstas até então. Atenção também para telas de Cadastro de Informante (Registro 10 e 11), Cadastro de Redução Z (Registros 60), Cadastro de GNRE (Registro 55) e etc que precisam ser criadas para satisfazer a geração de alguns registros específicos do Sintegra.

3. Validação das Informações + Tratamento de Erros: Para garantir o máximo de integridade e o mínimo de imprevistos no momento da geração do arquivo, é aconselhável que os dados passem pela camada de validação de informações antes de ir para o banco de dados. Assim, no momento da geração, você garante que os dados do banco estão consistentes.

4. Seleção das informações do Período: Esta é a tela de geração do arquivo propriamente dito, e nela deve haver uma implementação de seleção das informações a serem utilizadas para a geração do arquivo, normalmente feita através de Querys no banco de dados, aplicando à Select os filtros referentes ao período das informações, tipo de registros, bem como ordenação dos campos (order by) e agrupamentos (group by) caso necessário.

5. Chamadas para as Geração dos registros: As informações retornadas pelo banco de dados serão então passadas como parâmetros para as chamadas de geração dos registros sob a forma de loops nas Querys de seleção. As funções de geração dos registros, executam novamente o procedimento de validação das informações (Passo 6) e por fim, caso não seja encontrado erro nas informações transmitidas, executa a Composição dos Registros, colocando os parâmetros passados sob a forma descrita na legislação do sintegra.

Pronto! Uma vez de posse do retorno das funções de geração do registros, contendo os registros devidamente formatados, tudo o que o software gerencial tem a fazer é colocar a linha formatada em um arquivo .txt. Implementando o Sintegra com a SIntegra32Dll.dll

A Sintegra32dll.dll vem acompanhada de 2 demos que exemplificam sua utilização nos dois momentos descritos anteriormente. Para o Momento A há o demo sem utilização de banco de dados, onde são mostradas chamadas a todas as funções presentes na dll. Através de cliques nos botões respectivos você pode fazer os testes de cada função separadamente, como mostra a Figura 02.


Figura 02: Demo sem banco de dados. Chamadas a todas as funções disponíveis na Sintegra32dll.dll através do clique nos botões respectivos

No demo da Figura 02, para criação da linha do registro 50 descrita anteriormente, a chamada à função da dll no botão Registro 50 é feita como mostrado:

var
Form1: TForm1;

implementation
Function Registro50(CNPJ, Insc_Est, Data_Emissao_Recebimento, UF, Modelo, Serie,
                    Nro, CFOP, Emitente, Valor_Total, Base_ICMS, Valor_ICMS, Isenta, Outras,
                    Aliquota, Situacao: ShortString): ShortString; stdcall; external "SIntegra32Dll.DLL";
  
procedure TForm1.Button3Click(Sender: TObject);
var
 TempStr: String;
begin
//Registro50 - Registro de Total de Nota Fiscal
TempStr := Registro50("23.859.507/0001-09",       //CNPJ
                      "7.075.793.310.062",        //Insc_Est
                      "21/06/95",                 //Data_Emissao_Recebimento
                      "BA",                       //UF,
                      "1",                        //Modelo
                      "1",                        //Serie
                      "501306",                   //Nro
                      "5111",                     //CFOP
                      "P",                        //Emitente
                      "518,19",                   //Valor_Total
                      "518,19",                   //Base_ICMS
                      "36,27",                    //Valor_ICMS
                      "",                         //Isenta
                      "0,00",                     //Outras
                      "7,00",                     //Aliquota
                      "N"                         //Situacao
                     );
                 
 if TempStr[1] <> "-" then
  Memo1.Lines.Add(TempStr)  //Adiciona no Memo o Registro 50 formatado
 else
  ShowMessage(Copy(TempStr, 6, Length(TempStr)));	//Mostra a mensagem de erro recebida
end;

Para o Momento B há o demo com utilização de banco de dados, onde são mostradas chamadas aos principais registros do sintegra descritos anteriormente, sendo que as chamadas às funções da dll são feitas passando-se como parâmetros os valores contidos em um banco de dados Interbase, refletindo o exato comportamento que deve ser implementado pelo desenvolvedor quando na adaptação do seu sistema, incluindo as funções de tratamento de erros, log de erros na tela e criação do arquivo de texto.

A tela principal do demo com banco de dados é mostrada na Figura 03, e sua implementação será mostrada em detalhes neste artigo.


Figura 03: Demo com banco de dados. Chamadas a partir de um banco de dados Interbase às principais funções de registro do Sintegra disponíveis na Sintegra32dll.dll.

A principal funcionalidade do demo está implementada no botão Gerar Sintegra. Após o usuário preencher corretamente as informações da caixa superior sobre a Natureza das Operações, Finalidade do Arquivo, path do arquivo de saída .txt e período sobre o qual as informações devem ser geradas, e uma vez pressionado o botão Gerar Sintegra o programa segue o seguinte algoritmo:

  1. Verifica se o arquivo de saída já existe e se existir exclue o arquivo existente.
  2. Inicia o uso da Sintegra32dll.dll a partir de uma chamada à função Inicia_Sintegra.
  3. Realiza a chamada a uma determinada função de registro, que faz uma Query no banco de dados respectivo buscando pelas informações necessárias à geração do registro dentro do período desejado e na ordem de apresentação definida (order by).
  4. Realiza um loop na Query fazendo chamadas à Sintegra32dll.dll passando como parâmetros os resultados retornados pela Query, e armazenando em uma variável temporária a string retornada pela dll.
  5. Realiza a chamada a uma função de tratamento de erro passando como parâmetro a string temporária armazenada anteriormente, com o objetivo de verificar se a string contém descrição de erro ou o registro esperado devidamente formatado.
  6. Caso a string temporária contenha erro, é efetuado o log completo do erro na caixa de texto; caso contrário o registro devidamente formatado é adicionado ao arquivo de texto .txt.
  7. Repete-se os passos 2, 3, 4, 5 e 6 para todos os registros do Sintegra que se deseja gerar, tendo em vista características específicas do informante, como por exemplo se ele é ou não contribuinte do IPI (deve-se gerar registro 51), se ele é ou não Substituto Tributário (deve-se gerar registro 53). Tais informações devem ser armazenadas em uma tabela a ser preenchida previamente pelo usuário.

Vamos agora mostrar passo a passo a implementação do algoritmo descrito anteriormente para a confecção do registro 50 já apresentado nas situações anteriores.

No passo 1, executa-se a verificação se o arquivo de saída já existe e se existir exclue o arquivo existente.

if fileexists(edit1.Text) then
  begin
   Add_Log("Arquivo de saída existente excluído: " + edit1.Text, clred);
   deletefile(edit1.Text);
  end;
No passo 2, faz-se a chamada a função Inicia_Sintegra.
Inicia_Sintegra;

No passo 3, realiza-se a chamada à uma determinada função de registro, que faz uma Query no banco de dados respectivo buscando pelas informações necessárias à geração do registro dentro do período desejado e na ordem de apresentação definida (order by).

 //Geração de Registro50 quanto a Saída de Nota Fiscal
 //Executa a seleção dos registros no banco de dados
 with QrySintegra do
  begin
   Close;
   UnPrepare;
   SQL.Clear;

   SQL.Add("SELECT * FROM pedidos WHERE ");
   SQL.Add("(datahora_emissao BETWEEN :datahora_ini AND :datahora_fim) AND (");
   SQL.Add("(modelo_nf = ""01"") OR");
   SQL.Add("(modelo_nf = ""1A"") OR");
   SQL.Add("(modelo_nf = ""03"") OR");
   SQL.Add("(modelo_nf = ""06"") OR");
   SQL.Add("(modelo_nf = ""22""))");
   SQL.Add("ORDER BY datahora_emissao");

   ParamByName("datahora_ini").asdatetime := DataHora_Inicial;
   ParamByName("datahora_fim").asdatetime := DataHora_Final;
   Prepare;
   Open;
  end;

No passo 4, realiza-se um loop na Query fazendo chamadas à Sintegra32dll.dll passando como parâmetros os resultados retornados pela Query, e armazenando em uma variável temporária a string retornada pela dll.

if QrySintegra.RecordCount> 0 then
  begin
   while not QrySintegra.EOF do
    begin
     while not QrySintegra_D.EOF do
      begin
       num_nf := QrySintegra.Fields.FieldByName("num_nf").AsString;
       num_nf := trim(copy(num_nf, length(num_nf) - 6, length(num_nf)));  
//Faz a chamada da dll passando as informações do banco de dados e armazena numa string temporária
       TempStr := Registro50(QrySintegra.Fields.FieldByName("cnpj_destinatario").AsString, //CNPJ
         QrySintegra.Fields.FieldByName("ie_destinatario").AsString,                       //IE
         datetostr(QrySintegra.Fields.FieldByName("datahora_emissao").AsDateTime),         //Data
         QrySintegra.Fields.FieldByName("uf_destinatario").AsString,                       //UF,
         QrySintegra.Fields.FieldByName("modelo_nf").AsString,                             //Modelo
         QrySintegra.Fields.FieldByName("serie_nf").AsString,                              //Serie
         num_nf,                                                                           //Nro
         QrySintegra.Fields.FieldByName("cfop").AsString,                                  //CFOP
         QrySintegra.Fields.FieldByName("emitente_nf").AsString,                           //Emitent
         formatcurr("0.00", QrySintegra_D.Fields.FieldByName("subtotal").AsFloat),         //V_Total
         formatcurr("0.00", QrySintegra_D.Fields.FieldByName("base_icms").AsFloat),        //B_ICMS
         formatcurr("0.00", QrySintegra_D.Fields.FieldByName("valor_icms").AsFloat),       //V_ICMS
         formatcurr("0.00", QrySintegra.FieldByName("valor_isento_icms").AsFloat),         //Isenta
         formatcurr("0.00", QrySintegra.FieldByName("outras_despesas").AsFloat),           //Outras
         formatcurr("0.00", QrySintegra_D.Fields.FieldByName("aliquota_icms").AsFloat),    //Aliquot
         QrySintegra.Fields.FieldByName("situacao_nf").AsString                            //Situac
         );

Nos passos 5 e 6, realiza-se a chamada a uma função de tratamento de erro passando como parâmetro a string temporária armazenada anteriormente, como o objetivo de verificar se a string contém descrição de erro ou o registro devidamente formatado. Caso a string temporária contenha erro, é efetuado o log completo do erro na caixa de texto, caso contrário o registro devidamente formatado é adicionado ao arquivo de texto .txt.

       //Executa o tratamento da string temporária testando se houve erro
       //Caso haja erro, executa o log das informações inconsistentes no RichEdit
       if not Trata_SIntegra_Str(TempStr) then
        begin
         qnt_erro := qnt_erro + 1;
         Result := False;

         Err_Msg := Err_Msg + #13 +
           "    Cod_Pedidos: " + QrySintegra.Fields.FieldByName("cod_pedidos").AsString + #13 +
           "    CNPJ: " + QrySintegra.Fields.FieldByName("cnpj_destinatario").AsString + #13 +
           "    IE: " + QrySintegra.Fields.FieldByName("ie_destinatario").AsString + #13 +
           "    Emissao: " + datetostr(QrySintegra.Fields.FieldByName("datahora_emissao").AsDateTime) + #13 
+
           "    UF: " + QrySintegra.Fields.FieldByName("uf_destinatario").AsString + #13 +
           "    Modelo: " + QrySintegra.Fields.FieldByName("modelo_nf").AsString + #13 +
           "    Serie: " + QrySintegra.Fields.FieldByName("serie_nf").AsString + #13 +
           "    Nro: " + num_nf + #13 +
           "    CFOP: " + QrySintegra.Fields.FieldByName("cfop").AsString + #13 +
           "    Emitente: " + QrySintegra.Fields.FieldByName("emitente_nf").AsString + #13 +
           "    Valor_Total: " + QrySintegra_D.Fields.FieldByName("subtotal").AsString + #13 +
           "    Base ICMS: " + QrySintegra_D.Fields.FieldByName("base_icms").AsString + #13 +
           "    Valor ICMS: " + QrySintegra_D.Fields.FieldByName("valor_icms").AsString + #13 +
           "    Isenta: " + QrySintegra.FieldByName("valor_isento_icms").AsString + #13 +
           "    Outras: " + QrySintegra.FieldByName("outras_despesas").AsString + #13 +
           "    Aliquota: " + floattostr(QrySintegra_D.Fields.FieldByName("aliquota_icms").AsFloat * 100) + 
#13 +
           "    Situacao: " + QrySintegra.Fields.FieldByName("situacao_nf").AsString;
        end;

No passo 7, repete-se, os passos 2, 3, 4, 5 e 6 para todos os registros do Sintegra que se deseja gerar, tendo em vista características específicas do informante, como por exemplo se ele é ou não contribuinte do IPI (deve-se gerar registro 51), se ele é ou não Substituto Tributário (deve-se gerar registro 53). Assim o código para chamada e geração dos registros 10, 11, e 50 no botão Gerar Sintegra ficariam como segue:

procedure TSIntegra_ListFrm.BitBtn1Click(Sender: TObject);
begin
 DataHora_Inicial := StartOfTheMonth(Datetimepicker1.DateTime);
 DataHora_Final   := EndOfTheMonth(Datetimepicker1.DateTime);

 if fileexists(edit1.Text) then
  begin
   Add_Log("Arquivo de saída existente excluído: " + edit1.Text, clred);
   deletefile(edit1.Text);
  end;

 Inicia_Sintegra;

 if sRegistro10(Err_Msg) then
  Add_Log("1 Registro tipo 10 gerado com sucesso.", clgreen);
 else
  Add_Log("Erro durante criação do Registro tipo 10." + #13 +
     " Log de Erros: " + #13 + Err_Msg, clred);

 if sRegistro11(Err_Msg) then
  Add_Log("1 Registro tipo 11 gerado com sucesso.", clgreen);
 else
  Add_Log("Erro durante criação do Registro tipo 11." + #13 +
     " Log de Erros: " + #13 + Err_Msg, clred);

 if sRegistro50(Err_Msg, Qnt_Ok, Qnt_Erro) then
  begin
   if Qnt_Ok> 0 then
    Add_Log(inttostr(Qnt_Ok) + " Registro(s) tipo 50 gerado(s) com sucesso.", clgreen)
  end
 else
  begin
   if Qnt_Ok> 0 then
    Add_Log(inttostr(Qnt_Ok) + " Registro(s) tipo 50 gerado(s) com sucesso.", clgreen);

   Add_Log(inttostr(Qnt_Erro) + " Registro(s) tipo 50 não gerado(s) por Erro" + #13 +
     " Log de Erros: " + Err_Msg, clred);
  end;

Onde as funções sRegistro10, sRegistro11 e sRegistro50 executam internamente as funcionalidades descritas nos passos 3, 4, 5 e 6, para suas respectivas tabelas do banco de dados.

O arquivo de saída para o mês de 02/2004 gerado pelo demo, para os valores default que acompanham o banco de dados do mesmo é gerado sem erros e aceito pelo validador sem críticas e o resultado para a chamada do Registro 50 é mostrado de forma resumida a seguir, nele podemos visualizar os registros 10, 11 e 50 conforme a formatação do Sintegra, lembrando apenas que no caso do arquivo .txt o mesmo se apresenta sem quebra de linhas, sendo cada linha um registro.

103426113100014426858614      TKS Comercio e Servicos de TelefoniSalvador                      
BA00037118182004020120040229331
11Rua Casemiro Quiroga Loja D     00236Centro Comercial do ImImbui    41720050Gilmar Gomes 
Fernandes      000003711818
501470129600018202014120      20040202BA01   
0016651101T000000015530400000015530400000000000000000000000000000000000000001700N

Conclusão

Com este artigo, cobrimos os conceitos gerais acerca da implementação do sintegra, estruturação básica do sistema gerencial e o fluxograma de procedimentos a serem seguidos para a geração arquivo. Tendo sido demonstrado a partir do exemplo do registro 50 a forma geral de implementação, geração e tratamento de erros de um registro do sintegra a partir de informações contidas em um banco de dados Interbase.

No próximo artigo da série será descrito todo o processo de validação, visualização e transmissão do arquivo gerado, abordando as ferramentas oficiais disponíveis relacionadas ao tema.

Victory Fernandes

Victory Fernandes - Professor do Departamento de Engenharia da Faculdade Area1, Engenheiro Eletricista, Pós-Graduado em Docência, e desenvolvedor sócio da TKS Software - Soluções de Automação e Softwares Dedicados. Pode ser contatado em victory@igara.com.br, ou através dos sites www.igara.com.br - www.tkssoftware.com/victory