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;