Nossa empresa estar inserida numa região que comporta o terceiro pólo calçadista do país. No final de 2009 inicio de 2010 várias indústrias precisaram inserir nos seus ERPs a emissão da NF-e. Entre essas empresas estavam alguns clientes nossos. Além das indústrias de calçado outros clientes atacadistas e varejistas também precisavam emitir NF-e.

Com mais de um sistema para ser integrado com a NF-e passamos por um questionamento:

- Como minimizar o trabalho de manutenção dos ERPs para integrá-los a NF-e?

A resposta que encontramos foi a criação de um middleware que faça todo o processo de integração da NF-e com o mínimo de alteração em sistemas legados.

O middleware foi pensado e construído visando nos nossos sistemas legados em Delphi, e já preparado para, se preciso, integrá-lo com nossos sistemas legados feitos em outras linguagens.

No projeto do middleware foi analisado o tipo de comunicação que seria usada. A escolhida foi através de um layout simples e geração de arquivo texto. Dessa maneira qualquer sistema nosso, independente da linguagem de programação, poderia se comunicar com o middleware.

Do lado do ERP pensamos numa estratégia que diminuísse a curva de aprendizado do usuário final. Para isso criamos uma classe que é instanciada sempre que uma NF-e for emitida. Desta forma a única diferença observada pelo o usuário final seria em relação ao recebimento de mensagem de retorno do middleware informando o resultado do processamento.

Após conhecer nossa solução, alguns parceiros e colegas têm nos procurado para saber se tem como integrar o nosso middleware aos seus sistemas, em uma gama de linguagens diferentes, tais como Clipper, Delphi e Java. E o processo tem sido bem rápido, pois disponibilizamos a classe de comunicação que fica no ERP, que embora seja em Delphi, foi implementada de uma maneira bem simples e fácil de ser convertida para outras linguagens.

Os sistemas em Delphi estão sendo integrado em menos de 4 horas. Os de outras linguagens estão levando em média 8 horas. Após esta integração o sistema já está pronto para emitir a NF-e através do middleware.

Ao perceber o valor que o middleware agregou aos nossos parceiros, resolvemos disponibiliza-lo para softhouses que desejarem utilizar. A softhouse só precisa demonstrar interesse em usar o middleware para receber todo o apoio necessário para integração com custo zero.

Integração

De uma maneira geral a integração é simples, mas para os que haviam pedido ajuda lhes enviei uma classe de integração criada no Delphi, o que reduz ainda mais a curva de integração entre o nosso middleware e o ERP.

A classe que será apresentada é utilizada pelos nossos ERPs para fazer a emissão de NF-e via middleware. Embora o arquivo da classe seja grande, ela é bem simples e auto-explicativa. Mas caso exista alguma dúvida, por favor, nos comunique.

Na listagem abaixo é apresentado a declaração da classe TCASSICNFe e das constantes PathNFeIn e PathNFeOut. Estas duas constantes informam a classes TCASSICNFe onde colocar o arquivo de solicitação que será consumido pelo middleware (PathNFeIn) e onde o middleware irá colocar a reposta da solicitação feita (PathNFeOut).

Na mesma listagem é apresentado o construtor da classe (Create), o método que buscará o ID do município que será usado na geração da NF-e (MunicID) e o método que retorna a descrição do status da solicitação feita ao middleware (StatusNFe).

Observação:

O “Anexo II” do layout de integração contém a DDL da tabela Munic e os Insert de todos os municípios, com seus respectivos IDs e UF.


unit UCASSICNFe;

Interface

uses
  SysUtils, Dialogs, Forms, Windows, Controls, DB, SqlExpr;

type
  TCASSICNFe = class

  private
    FDataSet_Munic: TSQLQuery;
    FCNPJ: string;
    function MunicID(UF, Munic: string): string;
    function StatusNFe(Codigo: Integer): string;
    function MercuryMD(FilePath: string): Boolean;

  public
    constructor Create(CNPJ: string);
    function GerarNFe(DataSet_Munic, DataSet_DF, DataSet_DF_Item: TSQLQuery): Boolean;
    function ImprimirDANFE(ID_DF: string): Boolean;
    function CancelarNFe(ID_DF, Canc_Just: string): Boolean;
    function InutilizarNFe(NFe_Inicial, NFe_Final, Inut_Just: string): Boolean;
    function Enviar_eMailNFe(ID_DF, eMail: string): Boolean;
  end;

const
  // Endereço do arquivo de solicitação
  PathNFeIn = ''C:\Arquivos de Programas\CASSIC\Mercury-MD\In\'';

  // Endereço do arquivo de retorno do Mercury-MD
  PathNFeOut = ''C:\Arquivos de Programas\CASSIC\Mercury-MD\Out\''; 

implementation

{$I-}
constructor TCASSICNFe.Create(CNPJ: string);

begin
  FCNPJ := CNPJ;
end;

// Método para localizar o ID do município - "Anexo II" do layout de integração com o Mercury-MD
function TCASSICNFe.MunicID(UF, Munic: string): string;
begin
  with (FDataSet_Munic as TSQLQuery) do
    begin
      Active := False;
      SQL.Clear;
      SQL.Add(''select * from Munic'');
      SQL.Add(''where Cidade = ''''''+Munic+'''''''');
      SQL.Add(''and UF = ''''''+UF+'''''''');
      Active := True;
      if ( RecordCount = 0 ) then Result := ''0''
      else Result := FieldByName(''ID'').AsString;
    end;
end;

// Método que retorna a descrição do status da solicitação feita ao Mercury-MD
function TCASSICNFe.StatusNFe(Codigo: Integer): string;
begin
  case Codigo of
    -1: Result := ''Status não inicializado'';
    0: Result := ''Não criado XML'';
    1: Result := ''Criado XML'';
    2: Result := ''Não assinado'';
    3: Result := ''Assinado'';
    4: Result := ''Não validado'';
    5: Result := ''Validado'';
    6: Result := ''Lote não criado'';
    7: Result := ''Lote criado'';
    8: Result := ''Lote não enviado'';
    9: Result := ''Lote enviado'';
    10: Result := ''Lote não aceito'';
    11: Result := ''Lote aceita'';
    12: Result := ''Consulta não feita'';
    13: Result := ''Consulta feita'';
    14: Result := ''NF não aceita'';
    15: Result := ''NF aceita'';
    16: Result := ''NF aceita: Arquivo XML do e-mail não criado'';
    17: Result := ''NF aceita: Arquivo XML do e-mail criado'';
    18: Result := ''NF aceita: e-mail não enviado'';
    19: Result := ''NF aceita: e-mail enviado'';
    100: Result := ''Não criado XML'';
    101: Result := ''Criado XML'';
    102: Result := ''Não assinado'';
    103: Result := ''Assinado'';
    108: Result := ''Não enviado'';
    109: Result := ''Enviado'';
    114: Result := ''Cancelamento não aceito'';
    115: Result := ''Cancelamento aceito'';
    200: Result := ''Não criado XML'';
    201: Result := ''Criado XML'';
    202: Result := ''Não assinado'';
    203: Result := ''Assinado'';
    208: Result := ''Não enviado'';
    209: Result := ''Enviado'';
    214: Result := ''Inutilização não aceita'';
    215: Result := ''Inutilização aceita'';
    else Result := ''Status não esperado'';
  end;
end;

Na listagem seguinte é apresentada a primeira parte do método que gera o arquivo de solicitação para emissão da NF-e (GerarNFe). Embora o método seja grande, ele é simples, pois basicamente ele captura os dados da nota fiscal persistida no ERP e formata o arquivo de solicitação no mesmo local do aplicativo.

Observação1:

Devido o tamanho do método, ele não pode ser colocado num único artigo.

Observação2:

A geração do arquivo no mesmo Path do aplicativo é recomendada, pois isto evita que o middleware tente consumir um arquivo que ainda não foi finalizado pelo ERP.


// Método para gerar o arquivo de solicitação de emissão da NF-e
function TCASSICNFe.GerarNFe(DataSet_Munic, DataSet_DF, DataSet_DF_Item: TSQLQuery): Boolean;
var
  ArqDados: TextFile;
  Cont: Integer;
  FilePath: string;
  Munic, CFOPProd: string;
  CGF: string;

begin
  try
    Result := True;
    FDataSet_Munic := DataSet_Munic;
    Munic := MunicID(
      DataSet_DF.FieldByName('UF').AsString,
      DataSet_DF.FieldByName('Cidade').AsString);
    CGF := DataSet_DF.FieldByName('CGF').AsString;

    if ( Trim(CGF) = '' ) then CGF := 'ISENTO';

    // Arquivo temporário
    FilePath :=  ExtractFilePath( Application.Exename ) + '\NFE_SOLIC.TXT';
    FilePath := StringReplace(FilePath, '\\', '\', [rfReplaceAll]);

    // Inicia Arquivo NFE_SOLIC.TXT
    AssignFile(ArqDados, FilePath);
    Rewrite( ArqDados );

    /////////////////////////
    //                     //
    // Abertura do Arquivo //
    //                     //
    /////////////////////////

    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '0000' +
      FCNPJ);

    // Versão do Layout
    Writeln(ArqDados, '0001' +
      '01.01.001');

    // Tipo de mensagem
    Writeln(ArqDados, '0002' +
      '0001');

    /////////////////////////////////
    //                             //
    // Configuração da Nota Fiscal //
    //                             //
    /////////////////////////////////

    // ID da nota fiscal gerada no Aplicativo Cliente
    Writeln(ArqDados, '0500' +
      DataSet_DF.FieldByName('ID').AsString);

    ///////////////////////////////////////
    //                                   //
    // Dados Operacionais da Nota Fiscal //
    //                                   //
    ///////////////////////////////////////

    // Código da natureza da operação - Tabela XI
    Writeln(ArqDados, '1000' +
      DataSet_DF.FieldByName('Operacao').AsString);

    // Descrição da natureza da operação
    Writeln(ArqDados, '1005' +
      DataSet_DF.FieldByName('CFOPDescr').AsString);

    // CGF para a substituição tributária
    Writeln(ArqDados, '1010' +
      DataSet_DF.FieldByName('CGFSubst').AsString);

    // CFOP da nota fiscal
    Writeln(ArqDados, '1020' +
      DataSet_DF.FieldByName('CFOP').AsString);

    // Data de emissão da nota fiscal
    Writeln(ArqDados, '1030' +
      DataSet_DF.FieldByName('DtEmissao').AsString);

    // Data de saída ou entrada da nota fiscal, de acordo com o campo 1000
    Writeln(ArqDados, '1040' +
      DataSet_DF.FieldByName('DtSaida').AsString);

    // Hora da saída ou entrada da nota fiscal, de acordo com o campo 1000
    Writeln(ArqDados, '1050' +
      DataSet_DF.FieldByName('HsSaida').AsString);

    // Indicador da forma de pagamento - Tabela I
    Writeln(ArqDados, '1060' +
      DataSet_DF.FieldByName('Fatura').AsString);

    //////////////////////
    //                  //
    // Dados do Cliente //
    //                  //
    //////////////////////

    // Razão Social do cliente
    Writeln(ArqDados, '1100' +
      DataSet_DF.FieldByName('Cliente').AsString);

    // Logradouro do cliente
    Writeln(ArqDados, '1110' +
      DataSet_DF.FieldByName('Lograd').AsString);

    // Número do logradouro do cliente
    Writeln(ArqDados, '1111' +
      DataSet_DF.FieldByName('LogradNum').AsString);

    // Complemento do endereço do cliente
    Writeln(ArqDados, '1120' +
      '');

    // Bairro do cliente
    Writeln(ArqDados, '1130' +
      DataSet_DF.FieldByName('Bairro').AsString);

    // CEP do cliente
    Writeln(ArqDados, '1140' +
      DataSet_DF.FieldByName('CEP').AsString);

    // ID do município do cliente - Anexo II
    Writeln(ArqDados, '1150' +
      Munic);

    // Unidade federativa do cliente
    Writeln(ArqDados, '1160' +
      DataSet_DF.FieldByName('UF').AsString);

    // ID do país do cliente. Anexo III
    Writeln(ArqDados, '1170' +
      '1058');

    // Número do telefone do cliente
    Writeln(ArqDados, '1180' +
      DataSet_DF.FieldByName('Fone').AsString);

    // e-mail do cliente
    Writeln(ArqDados, '1190' +
      DataSet_DF.FieldByName('eMail').AsString);

    // CNPJ do cliente
    Writeln(ArqDados, '1200' +
      DataSet_DF.FieldByName('CNPJ').AsString);

    // CPF do cliente
    Writeln(ArqDados, '1201' +
      DataSet_DF.FieldByName('CPF').AsString);

    // CGF do cliente
    Writeln(ArqDados, '1210' +
      CGF);

    // SUFRAMA do cliente
    Writeln(ArqDados, '1220' +
      DataSet_DF.FieldByName('SUFRAMA').AsString);
// Método para gerar o arquivo de solicitação de emissão da NF-e
function TCASSICNFe.GerarNFe(DataSet_Munic, DataSet_DF, DataSet_DF_Item: TSQLQuery): Boolean;

    ////////////////////////////
    //                        //
    // Dados do Transportador //
    //                        //
    ////////////////////////////
    // Nome do transportador

    Writeln(ArqDados, ''1300'' +
      DataSet_DF.FieldByName(''Transp'').AsString);

    // CNPJ do transportador
    Writeln(ArqDados, ''1310'' +
      DataSet_DF.FieldByName(''TrIdent'').AsString);

    // CPF do transportador
    Writeln(ArqDados, ''1311'' +
      '''');

    // CGF do transportador
    Writeln(ArqDados, ''1320'' +
      '''');

    // Endereço do transportador
    Writeln(ArqDados, ''1330'' +
      DataSet_DF.FieldByName(''TrEnder'').AsString);

    // Nome do município do Transportador
    Writeln(ArqDados, ''1340'' +
      DataSet_DF.FieldByName(''TrCidade'').AsString);

    // Unidade federativa do Transportador
    Writeln(ArqDados, ''1350'' +
      DataSet_DF.FieldByName(''TrUF'').AsString);

    //////////////////////
    //                  //
    // Dados do Veículo //
    //                  //
    //////////////////////

    // Placa do veículo utilizado pelo Transportador
    Writeln(ArqDados, ''1400'' +
      DataSet_DF.FieldByName(''TrPlaca'').AsString);

    // Unidade federativa do veículo utilizado pelo Transportador
    Writeln(ArqDados, ''1410'' +
      DataSet_DF.FieldByName(''TrUFVeic'').AsString);

    // Registro Nacional de Transportador de Carga (ANTT)
    Writeln(ArqDados, ''1420'' +
      '''');

    ////////////////////
    //                //
    // Dados do Frete //
    //                //
    ////////////////////

    // Modalidade do frete. Tabela II
    Writeln(ArqDados, ''1500'' +
      DataSet_DF.FieldByName(''Frete'').AsString);

    // Quantidade de volumes transportados
    Writeln(ArqDados, ''1510'' +
      DataSet_DF.FieldByName(''QtVol'').AsString);

    // Espécie dos volumes transportados
    Writeln(ArqDados, ''1520'' +
      DataSet_DF.FieldByName(''Especie'').AsString);

    // Marca dos volumes transportados
    Writeln(ArqDados, ''1530'' +
      DataSet_DF.FieldByName(''Marca'').AsString);

    // Numeração dos volumes transportados
    Writeln(ArqDados, ''1540'' +
      DataSet_DF.FieldByName(''Numero'').AsString);

    // Peso bruto dos volumes transportados
    Writeln(ArqDados, ''1550'' +
      DataSet_DF.FieldByName(''PesoBruto'').AsString);

    // Peso liquido dos volumes transportados
    Writeln(ArqDados, ''1560'' +
      DataSet_DF.FieldByName(''PesoLiq'').AsString);

    //////////////////////////////////
    //                              //
    // Totalizadores da Nota Fiscal //
    //                              //
    //////////////////////////////////

    // Valor total do ICMS
    Writeln(ArqDados, ''1600'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''NVrICMS'').AsCurrency]));

    // Base de calculo do ICMS
    Writeln(ArqDados, ''1605'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''NBaseICMS'').AsCurrency]));

    // Valor total do ICMS substituição tributária
    Writeln(ArqDados, ''1610'' +
      '''');

    // Base de calculo do ICMS substituição tributária
    Writeln(ArqDados, ''1615'' +
      '''');

    // Valor total do IPI
    Writeln(ArqDados, ''1620'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''NVrIPI'').AsCurrency]));

    // Valor total do PIS
    Writeln(ArqDados, ''1630'' +
      '''');

    // Valor total do COFINS
    Writeln(ArqDados, ''1640'' +
      '''');

    // Valor total da NF-e
    Writeln(ArqDados, ''1700'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''VrDF'').AsCurrency]));

    // Valor total de produtos ou serviços
    Writeln(ArqDados, ''1710'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''Valor'').AsCurrency]));

    // Valor total do frete
    Writeln(ArqDados, ''1720'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''VrFrete'').AsCurrency]));

    // Valor total do seguro
    Writeln(ArqDados, ''1730'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''VrSeguro'').AsCurrency]));

    // Valor total do desconto
    Writeln(ArqDados, ''1740'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''VrDescont'').AsCurrency]));

    // Valor total de outras despesas acessórias
    Writeln(ArqDados, ''1750'' +
      Format(''%1.2f'', [DataSet_DF.FieldByName(''VrOutras'').AsCurrency]));

    /////////////////////////////////////////
    //                                     //
    // Dados Complementares da Nota Fiscal //
    //                                     //
    /////////////////////////////////////////

    // Dados complementares do contribuinte
    Writeln(ArqDados, ''2000'' +
      DataSet_DF.FieldByName(''Obs'').AsString);

    for Cont := 2001 to 2003 do
      Writeln(ArqDados, IntToStr(Cont) +
        '''');                     

    // Informações adicionais para o fisco
    Writeln(ArqDados, ''2100'' +
      '''');

	  // Método para gerar o arquivo de solicitação de emissão da NF-e   
function TCASSICNFe.GerarNFe(DataSet_Munic, DataSet_DF, DataSet_DF_Item: TSQLQuery): Boolean;

    // Primeiro item
    DataSet_DF_Item.First;

    // Enquanto não for o fim
    while not( DataSet_DF_Item.Eof ) do
      begin
        CFOPProd := Trim(DataSet_DF_Item.FieldByName('CFOP').AsString);
        if ( CFOPProd = '' ) then CFOPProd := Trim(
          DataSet_DF.FieldByName('CFOP1').AsString);

        ///////////////////////////////////
        //                               //
        // Dados Operacionais do Produto //
        //                               //
        ///////////////////////////////////

        // ID do produto
        Writeln(ArqDados, '3000' +
          DataSet_DF_Item.FieldByName('IDProd').AsString);

        // Descrição do produto
        Writeln(ArqDados, '3010' +
          DataSet_DF_Item.FieldByName('Prod').AsString);

        // Unidade comercial do produto
        Writeln(ArqDados, '3020' +
          DataSet_DF_Item.FieldByName('Unid').AsString);

        // Quantidade vendida do produto
        Writeln(ArqDados, '3030' +
          Format('%1.4f', [DataSet_DF_Item.FieldByName('Quant').AsCurrency]));

        // Valor unitário do produto
        Writeln(ArqDados, '3040' +
          Format('%1.4f', [DataSet_DF_Item.FieldByName('VrLiq').AsCurrency]));

        //////////////////////////////
        //                          //
        // Totalizadores do Produto //
        //                          //
        //////////////////////////////

        // Valor total do produto
        Writeln(ArqDados, '3100' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('TotalLiq').AsCurrency]));

        // Unidade tributável do produto
        Writeln(ArqDados, '3110' +
          DataSet_DF_Item.FieldByName('Unid').AsString);

        // Valor tributável do produto
        Writeln(ArqDados, '3120' +
          Format('%1.4f', [DataSet_DF_Item.FieldByName('TotalLiq').AsCurrency]));

        // Valor do ICMS do produto
        Writeln(ArqDados, '3130' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('NVrICMS').AsCurrency]));

        // Base de calculo do ICMS do produto
        Writeln(ArqDados, '3135' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('NBaseICMS').AsCurrency]));

        // Alíquota do ICMS do produto
        Writeln(ArqDados, '3136' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('NICMS').AsCurrency]));

        // Valor total do ICMS substituição tributária do produto
        Writeln(ArqDados, '3140' +
          '');

        // Base de calculo do ICMS substituição tributária do produto
        Writeln(ArqDados, '3145' +
          '');

        // Alíquota do ICMS substituição tributária do produto
        Writeln(ArqDados, '3146' +
          '');

        // Valor de IPI do produto
        Writeln(ArqDados, '3150' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('NVrIPI').AsCurrency]));

        // Base de calculo de IPI do produto
        Writeln(ArqDados, '3155' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('BaseIPI').AsCurrency]));

        // Alíquota de IPI do produto
        Writeln(ArqDados, '3156' +
          Format('%1.2f', [DataSet_DF_Item.FieldByName('NIPI').AsCurrency]));

        // Valor de PIS do produto
        Writeln(ArqDados, '3160' +
          '');

        // Base de calculo de PIS do produto
        Writeln(ArqDados, '3165' +
          '');

        // Alíquota de PIS do produto
        Writeln(ArqDados, '3166' +
          '');

        // Valor de COFINS do produto
        Writeln(ArqDados, '3170' +
          '');

        // Base de calculo de COFINS do produto
        Writeln(ArqDados, '3175' +
          '');

        // Alíquota de COFINS do produto
        Writeln(ArqDados, '3176' +
          '');

        /////////////////////////////////////
        //                                 //
        // Dados Complementares do Produto //
        //                                 //
        /////////////////////////////////////

        // Código GTIN do produto, antigo código EAN (Código de barras)
        Writeln(ArqDados, '3200' +
          '');

        // Nomenclatura comum do MERCOSUL
        Writeln(ArqDados, '3210' +
          '');

        // CFOP do produto
        Writeln(ArqDados, '3220' +
          CFOPProd);

        // Origem do produto - Tabela III
        Writeln(ArqDados, '3230' +
          Copy(DataSet_DF_Item.FieldByName('CST').AsString, 1, 1));

        // Código da situação tributária de ICMS - Tabela IV
        Writeln(ArqDados, '3240' +
          Copy(DataSet_DF_Item.FieldByName('CST').AsString, 2, 2));

        // Modalidade de determinação da base de calculo de ICMS do produto - Tabela V
        Writeln(ArqDados, '3250' +
          '3');

        // Modalidade de determinação da base de calculo do ICMS substituição tributária do produto - Tabela VI
        Writeln(ArqDados, '3260' +
          '');

        // Código da situação tributária de IPI - Tabela VII
        Writeln(ArqDados, '3270' +
          '52');

        // Código da situação tributária de PIS - Tabela IX
        Writeln(ArqDados, '3280' +
          '07');

        // Código da situação tributária de COFINS - Tabela X
        Writeln(ArqDados, '3290' +
          '07');

        // Próximo item
        DataSet_DF_Item.Next;
      end;

    ///////////////////////////
    //                       //
    // Fechamento do Arquivo //
    //                       //
    ///////////////////////////

    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '9999' +
      FCNPJ);

    // Finaliza Arquivo NFE_SOLIC.TXT
    CloseFile(ArqDados);

    // Abre comunicação com o MercuryMD
    Result := MercuryMD(FilePath);
  except
    Result := False;
  end;
end;

Na listagem seguinte é mostrado o método responsável por integrar o ERP com o middleware (MercuryMD). Ele cópia para a pasta de solicitação o arquivo gerado pelos métodos GerarNFe, ImprimirDANFE, CancelarNFe, InutilizarNFe e Enviar_eMailNFe. Na seqüência o método fica aguardando o arquivo de retorno gerado pelo middleware para poder processar a resposta.


// Método que integra o ERP ao Mercury-MD
//   1 - Enviar o arquivo de solicitação
//   2 - Recebe o arquivo de resposta

function TCASSICNFe.MercuryMD(FilePath: string): Boolean;
var
  ArqDados: TextFile;
  FilePathSolic, FilePathResp: string;
  Campo9999, StrLn, MsgErro, MsgStatus, Processada, Restante: string;
  TamLn, TtlErro, CodStatus: Integer;
  TipMsg, TipMsgRet: string;
  Cont: Integer;
  Flag: Longbool;
begin
  Result := False;

  // Arquivo enviado ao Mercury-MD
  FilePathSolic := PathNFeIn  + ''\NFE_SOLIC.TXT'';
  FilePathSolic := StringReplace(FilePathSolic, ''\\'', ''\'', [rfReplaceAll]);

  // Arquivo recebido do Mercury-MD
  FilePathResp := PathNFeOut  + ''\NFE_RESP.TXT'';
  FilePathResp := StringReplace(FilePathResp, ''\\'', ''\'', [rfReplaceAll]);

  if ( FileExists(FilePathSolic) ) then DeleteFile( PChar(FilePathSolic) );
  if ( FileExists(FilePathResp) ) then DeleteFile( PChar(FilePathResp) );
  CopyFile( PChar(FilePath), PChar(FilePathSolic), Flag );
  Cont := 0;
  while ( True ) do
    begin
      Application.ProcessMessages;
      Inc(Cont);
      // Se o arquivo de resposta ainda não foi gerado pelo Mercury-MD
      if not( FileExists(FilePathResp) ) then
        begin
          if ( Cont = 10 ) then
            begin
              if ( MessageDlg(''Resposta do Mercury-MD ainda não recebido.'' +#13#13+
                ''Por favor, verifique se Mercury-MD está ativo.'' +#13#13+
                  ''Permanece aguardando?'', mtConfirmation,
                    [mbYes, mbNo], 0) <> mrYes ) then Exit;
              Cont := 0;
            end;
          Sleep(10000);
        end
      // Se o arquivo de resposta foi gerado pelo Mercury-MD
      else
        begin
          TtlErro := 0;
          MsgErro := '''';
          MsgStatus := ''Status não processado'';
          Processada := '''';
          Restante := ''0'';
          AssignFile(ArqDados, FilePathResp);
          Reset(ArqDados);
          while not( Eof(ArqDados) ) do
            begin
              ReadLn(ArqDados, StrLn);
              TamLn := Length(StrLn) - 4;
              // Tipo de mensagem
              if ( Copy(StrLn, 1, 4) = ''0002'' )
                then TipMsg := Copy(StrLn, 5, TamLn)
              // Erros nas Rotinas NFe
              else if ( Copy(StrLn, 1, 2) = ''01'' ) then
                begin
                  if ( Copy(StrLn, 3, 2) = ''00'' )
                    then TtlErro := StrToInt( Copy(StrLn, 5, TamLn) )
                  else MsgErro := MsgErro + #13#13+ ''"'' + Copy(StrLn, 5, TamLn) + ''"'';
                end
              // Dados de Retorno do CASSICNF-e ---> Status
              else if ( Copy(StrLn, 1, 4) = ''0620'' ) then
                begin
                  CodStatus := StrToInt( Copy(StrLn, 5, TamLn) );
                  MsgStatus := IntToStr(CodStatus);
                  MsgStatus := MsgStatus + '' - '' + StatusNFe(CodStatus);
                end
              // Mensagens de Controles
              else if ( Copy(StrLn, 1, 2) = ''99'' ) then
                begin
                  if ( Copy(StrLn, 3, 2) = ''80'' )
                    then Processada := Copy(StrLn, 5, TamLn)
                  else if ( Copy(StrLn, 3, 2) = ''90'' )
                    then Restante := Copy(StrLn, 5, TamLn);
                end;
            end;
          CloseFile(ArqDados);
          DeleteFile( PChar(FilePathResp) );
          MsgStatus := ''Status da NF-e: '' + MsgStatus;
          if ( TtlErro <> 0 ) then
            begin
              MessageDlg(MsgStatus +#13#13+
                ''Total de erros: '' + IntToStr(TtlErro) +#13#13+
                ''Messagens de erros: '' + MsgErro, mtError, [mbOk], 0);
              Exit;
            end;
          TipMsgRet := '''';
          if ( TipMsg = ''0001'' ) then TipMsgRet :=
            ''Nota fiscal processada: '' + Processada +#13+
            ''NF-e disponíveis: '' + Restante;
          MessageDlg(MsgStatus +#13+ TipMsgRet, mtInformation, [mbOk], 0);
           
          Result := True;
          Exit;
        end;
    end;
end;

Para finalizar a classe de integração TCASSICNFe, o métodos ImprimirDANFE e CancelarNFe são apresentado na listagem abaixo.


// Método para gerar o arquivo de solicitação de impressão do DANFE
function TCASSICNFe.ImprimirDANFE(ID_DF: string): Boolean;
var
  ArqDados: TextFile;
  FilePath: string;
  Cont: Integer;
begin
  try
    Result := True;
    // Arquivo temporário
    FilePath :=  ExtractFilePath( Application.Exename ) + '\NFE_SOLIC.TXT';
    FilePath := StringReplace(FilePath, '\\', '\', [rfReplaceAll]);
    // Inicia Arquivo NFE_SOLIC.TXT
    AssignFile(ArqDados, FilePath);
    Rewrite( ArqDados );
    /////////////////////////
    //                     //
    // Abertura do Arquivo //
    //                     //
    /////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '0000' +
      FCNPJ);
    // Versão do Layout
    Writeln(ArqDados, '0001' +
      '01.01.001');
    // Tipo de mensagem
    Writeln(ArqDados, '0002' +
      '0004');
    /////////////////////////////////
    //                             //
    // Configuração da Nota Fiscal //
    //                             //
    /////////////////////////////////
    // ID da nota fiscal gerada no Aplicativo Cliente
    Writeln(ArqDados, '0500' +
      ID_DF);
    ///////////////////////////
    //                       //
    // Fechamento do Arquivo //
    //                       //
    ///////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '9999' +
      FCNPJ);
    // Finaliza Arquivo NFE_SOLIC.TXT
    CloseFile(ArqDados);
    // Abre comunicação com o MercuryMD
    Result := MercuryMD(FilePath);
  except
    Result := False;
  end;
end;
// Método para gerar o arquivo de solicitação de cancelamento da NF-e
function TCASSICNFe.CancelarNFe(ID_DF, Canc_Just: string): Boolean;
var
  ArqDados: TextFile;
  FilePath: string;
  Cont: Integer;
begin
  try
    Result := True;
    // Arquivo temporário
    FilePath :=  ExtractFilePath( Application.Exename ) + '\NFE_SOLIC.TXT';
    FilePath := StringReplace(FilePath, '\\', '\', [rfReplaceAll]);
    // Inicia Arquivo NFE_SOLIC.TXT
    AssignFile(ArqDados, FilePath);
    Rewrite( ArqDados );
    /////////////////////////
    //                     //
    // Abertura do Arquivo //
    //                     //
    /////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '0000' +
      FCNPJ);
    // Versão do Layout
    Writeln(ArqDados, '0001' +
      '01.01.001');
    // Tipo de mensagem
    Writeln(ArqDados, '0002' +
      '0002');
    /////////////////////////////////
    //                             //
    // Configuração da Nota Fiscal //
    //                             //
    /////////////////////////////////
    // ID da nota fiscal gerada no Aplicativo Cliente
    Writeln(ArqDados, '0500' +
      ID_DF);
    // Justificativa do cancelamento
    Writeln(ArqDados, '0520' +
      Canc_Just);
    ///////////////////////////
    //                       //
    // Fechamento do Arquivo //
    //                       //
    ///////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '9999' +
      FCNPJ);
    // Finaliza Arquivo NFE_SOLIC.TXT
    CloseFile(ArqDados);
    // Abre comunicação com o MercuryMD
    Result := MercuryMD(FilePath);
  except
    Result := False;
  end;
end;

Para finalizar a classe de integração TCASSICNFe, os métodos InutilizarNFe e Enviar_eMailNFe são apresentado na listagem abaixo.


// Método para gerar o arquivo de solicitação de inutilização de NF-e
function TCASSICNFe.InutilizarNFe(NFe_Inicial, NFe_Final, Inut_Just: string): Boolean;
var
  ArqDados: TextFile;
  FilePath: string;
  Cont: Integer;
begin
  try
    Result := True;
    // Arquivo temporário
    FilePath :=  ExtractFilePath( Application.Exename ) + '\NFE_SOLIC.TXT';
    FilePath := StringReplace(FilePath, '\\', '\', [rfReplaceAll]);
    // Inicia Arquivo NFE_SOLIC.TXT
    AssignFile(ArqDados, FilePath);
    Rewrite( ArqDados );
    /////////////////////////
    //                     //
    // Abertura do Arquivo //
    //                     //
    /////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '0000' +
      FCNPJ);
    // Versão do Layout
    Writeln(ArqDados, '0001' +
      '01.01.001');
    // Tipo de mensagem
    Writeln(ArqDados, '0002' +
      '0003');
    /////////////////////////////////
    //                             //
    // Configuração da Nota Fiscal //
    //                             //
    /////////////////////////////////
    // Justificativa da inutilização
    Writeln(ArqDados, '0520' +
      Inut_Just);
    ////////////////////////
    //                    //
    // Dados do CASSICNFE //
    //                    //
    ////////////////////////
    // ID da primeira nota fiscal eletrônica inutilizada no CASSICNFE
    Writeln(ArqDados, '0600' +
      NFe_Inicial);
    // ID da última nota fiscal eletrônica inutilizada no CASSICNFE
    Writeln(ArqDados, '0601' +
      NFe_Final);
    ///////////////////////////
    //                       //
    // Fechamento do Arquivo //
    //                       //
    ///////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '9999' +
      FCNPJ);
    // Finaliza Arquivo NFE_SOLIC.TXT
    CloseFile(ArqDados);
    // Abre comunicação com o MercuryMD
    Result := MercuryMD(FilePath);
  except
    Result := False;
  end;
end;
// Método para gerar o arquivo de solicitação de reenvio de e-mail da NF-e já emitida
function TCASSICNFe.Enviar_eMailNFe(ID_DF, eMail: string): Boolean;
var
  ArqDados: TextFile;
  FilePath: string;
  Cont: Integer;
begin
  try
    Result := True;
    // Arquivo temporário
    FilePath :=  ExtractFilePath( Application.Exename ) + '\NFE_SOLIC.TXT';
    FilePath := StringReplace(FilePath, '\\', '\', [rfReplaceAll]);
    // Inicia Arquivo NFE_SOLIC.TXT
    AssignFile(ArqDados, FilePath);
    Rewrite( ArqDados );
    /////////////////////////
    //                     //
    // Abertura do Arquivo //
    //                     //
    /////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '0000' +
      FCNPJ);
    // Versão do Layout
    Writeln(ArqDados, '0001' +
      '01.01.001');
    // Tipo de mensagem
    Writeln(ArqDados, '0002' +
      '0005');
    /////////////////////////////////
    //                             //
    // Configuração da Nota Fiscal //
    //                             //
    /////////////////////////////////
    // ID da nota fiscal gerada no Aplicativo Cliente
    Writeln(ArqDados, '0500' +
      ID_DF);
    //////////////////////
    //                  //
    // Dados do Cliente //
    //                  //
    //////////////////////
    // e-mail do cliente
    if ( eMail <> '' ) then Writeln(ArqDados, '1190' + eMail);
     
    ///////////////////////////
    //                       //
    // Fechamento do Arquivo //
    //                       //
    ///////////////////////////
    // CNPJ da empresa usuária do CASSIC NF-e
    Writeln(ArqDados, '9999' +
      FCNPJ);
    // Finaliza Arquivo NFE_SOLIC.TXT
    CloseFile(ArqDados);
    // Abre comunicação com o MercuryMD
    Result := MercuryMD(FilePath);
  except
    Result := False;
  end;
end;