terça-feira, 4 de janeiro de 2011

TEF - Realizando operações administrativas

Nesta parte, estaremos realizando algumas operações administrativas que são necessárias no desenvolvimento do TEF. É através do módulo administrativo da bandeira (AMEX, Redecard ou Visanet) que são realizadas operações, como:

- reimpressão da transação TEF.
- cancelamentos.
- impressão de relatórios.
- fechamento de lotes.
- inicialização de terminal.
- configurações.

Iremos desenvolver a rotina de chamada do módulo administrativo e a impressão do conteúdo da operação, através do relatório gerencial (em anexo), caso necessário. Também é necessário confirmar a operação, quando houver texto a ser impresso.

A função de confirmação (ConfirmaTransacao) foi visto na edição 8 de seu FlashTip.

- Exemplo em Delphi

.
.
.
cIdentificacao := Time;
FuncaoAdministrativaTEF( cIdentificacao );
if ( ImprimeGerencial = 1 ) then
 ConfirmaTransacao;
.
.
.

////////////////////////////////////////////////////////////////////////////////
// Função: FuncaoAdministrativaTEF
// Objetivo: Chamar o módulo administrativo da bandeira
// Parâmetro: String com o identificador
// Retorno: 1 para OK
//          diferente de 1 para não OK //////////////////////////////////////////////////////////////////////////////// function FuncaoAdministrativaTEF( cIdentificacao: TDateTime ): integer;
var cArquivo: TextFile;
lFlag: longbool;
cConteudoArquivo: string;
begin
 AssignFile( cArquivo, 'INTPOS.001');
 // Conteúdo do arquivo INTPOS.001 para solicitar a transação TEF
 cConteudoArquivo := '';
 cConteudoArquivo := '000-000 = ADM' + #13 + #10 +
    '001-000 = ' + FormatDateTime( 'hhmmss', cIdentificacao ) + #13 + #10 +
    '999-999 = 0';
 ReWrite( cArquivo );
 WriteLn( cArquivo, cConteudoArquivo );
 CloseFile( cArquivo );
 CopyFile( pchar( 'INTPOS.001' ), pchar( 'C:\TEF_DIAL\REQ\INTPOS.001' ),
   lFlag );
 DeleteFile( 'INTPOS.001' );
end;

TEF - Tratando a situação de queda de energia

Conforme mencionamos na parte anterior, nesta parte estaremos tratando a situação de queda de energia, quando ocorre durante a impressão da transação TEF e o que devemos fazer.

Quando nos deparamos com esta situação, o importante é verificarmos se existe uma transação pendente, mas como verificar isso se a aplicação foi reinicializada? Simples! Vamos usar uma lógica externa para tratar este tipo de situação, criando o arquivo TEF.TXT, toda a vez que iniciarmos a impressão da transação TEF e elimina-lo quando esta transação for concluída, assim ao entrarmos na aplicação poderemos verificar a existência deste arquivo e não confirmar a transação pendente.

Serão utilizados os códigos já desenvolvidos, incluindo esta nova implementação e, em anexo, seguirão os códigos completos em Delphi e Visual Basic.

- Exemplo em Delphi

// Form Create
procedure TfrmPrincipal.FormCreate(Sender: TObject);
var iRetorno: integer;
begin
 // Verifica se existe o arquivo TEF.TXT, indicando que há uma
 // transação pendente.
 if FileExists( 'TEF.TXT' ) then
     begin
       iRetorno := Bematech_FI_FechaComprovanteNaoFiscalVinculado;
       NaoConfirmaTransacao;
       if FileExists( 'TEF.TXT' ) then
         DeleteFile( 'TEF.TXT' );
     end;
end;

////////////////////////////////////////////////////////////////////////////////
// Função: ImprimeTransacao
// Objetivo: Realiza a impressão da Transação TEF
// Parâmetros: string para a Forma de Pagamento
//             string para a Valor da Forma de Pagamento
//             string para o Número do Cupom Fiscal (COO)
//             TDateTime para identificar o número da transação
// Retorno: True para OK ou False para não OK
////////////////////////////////////////////////////////////////////////////////
function ImprimeTransacao( cFormaPGTO: string; cValorPago: string;
  cCOO: string; cIdentificacao: TDateTime ): boolean;
var cLinhaArquivo, cLinha, cSaltaLinha, cConteudo: string;
  cMensagem: TForm;
  cArquivo : TextFile;
  iVezes : integer;
begin

 // Neste ponto é criado o arquivo TEF.TXT, indicando que há uma
  // operação de TEF sendo realizada. Caso ocorra uma queda de energia,
  // no momento da impressão do TEF, e a aplicação for inicializada,
  // ao identificar a existência deste arquivo, a transação do TEF
  // deverá ser concelada.
  AssignFile( cArquivo, 'TEF.TXT');
  ReWrite( cArquivo );
  CloseFile( cArquivo );

  // Bloqueia o teclado e o mouse para a impressão do TEF
  iRetorno := Bematech_FI_IniciaModoTEF();

  result := true;
  if FileExists( 'IMPRIME.TXT') then
      begin
        iRetorno := Bematech_FI_AbreComprovanteNaoFiscalVinculado( pchar(
           cFormaPGTO ), pchar( cValorPago ), pchar( cCOO ) );
        .
        .
        .

////////////////////////////////////////////////////////////////////////////////
// Função: ConfirmaTransacao
// Objetivo: Confirmar a Transação TEF
// Parâmetros: não há
// Retorno: True para OK ou False para não OK
////////////////////////////////////////////////////////////////////////////////
function ConfirmaTransacao: boolean;
var cLinhaArquivo, cConteudo: string;
  cArquivo: TextFile;
  lFlag : longbool;
begin
  cLinhaArquivo := '';
  cConteudo := '';
  AssignFile( cArquivo, 'C:\TEF_DIAL\RESP\INTPOS.001' );
  Reset( cArquivo );
  while not EOF( cArquivo ) do
      begin
         ReadLn( cArquivo, cLinhaArquivo );
        if ( copy( cLinhaArquivo, 1, 3 ) = '001' ) or
           ( copy( cLinhaArquivo, 1, 3 ) = '002' ) or
           ( copy( cLinhaArquivo, 1, 3 ) = '010' ) or
           ( copy( cLinhaArquivo, 1, 3 ) = '012' ) or
           ( copy( cLinhaArquivo, 1, 3 ) = '027' ) then
           cConteudo := cConteudo + cLinhaArquivo + #13 + #10;
        if ( copy( cLinhaArquivo, 1, 3 ) = '999' ) then
           cConteudo := cConteudo + cLinhaArquivo;
     end;
  CloseFile( cArquivo );
  cConteudo := '000-000 = CNF' + #13 + #10 + cConteudo;
  AssignFile( cArquivo, 'INTPOS.001' );
  ReWrite( cArquivo );
  WriteLn( cArquivo, cConteudo );
  CloseFile( cArquivo );
  CopyFile( pchar( 'INTPOS.001' ), pchar( 'C:\TEF_DIAL\REQ\INTPOS.001' ),
      lFlag );
  DeleteFile( 'INTPOS.001' );
  if ( FileExists( 'C:\TEF_DIAL\RESP\INTPOS.STS' ) ) then
     DeleteFile( 'C:\TEF_DIAL\RESP\INTPOS.STS' );
  if ( FileExists( 'C:\TEF_DIAL\RESP\INTPOS.001' ) ) then
     DeleteFile( 'C:\TEF_DIAL\RESP\INTPOS.001' );

  // Se o arquivo TEF.TXT, que identifica que houve uma transação impressa
  // existir, o mesmo será exluído.
  if ( FileExists( 'TEF.TXT' ) ) then
     DeleteFile( 'TEF.TXT' );
end;

////////////////////////////////////////////////////////////////////////////////
// Função: NaoConfirmaTransacao
// Objetivo: Não Confirmar a Transação TEF
// Parâmetros: não há
// Retorno: True para OK ou False para não OK
////////////////////////////////////////////////////////////////////////////////
function NaoConfirmaTransacao: boolean;
var cLinhaArquivo, cConteudo: string;
  cArquivo: TextFile;
  lFlag : longbool;
  cValor, cNomeRede, cNSU: string;
begin
  cLinhaArquivo := '';
  cConteudo := '';
  AssignFile( cArquivo, 'C:\TEF_DIAL\RESP\INTPOS.001' );
  Reset( cArquivo );
  while not EOF( cArquivo ) do
     begin
        ReadLn( cArquivo, cLinhaArquivo );
        if ( copy( cLinhaArquivo, 1, 3 ) = '001' ) then
           cConteudo := cConteudo + cLinhaArquivo + #13 + #10;
        if ( copy( cLinhaArquivo, 1, 3 ) = '003' ) then
           cValor := copy( cLinhaArquivo, 11, Length( cLinhaArquivo ) - 10 );
        if ( copy( cLinhaArquivo, 1, 3 ) = '010' ) then
           begin
              cConteudo := cConteudo + cLinhaArquivo + #13 + #10;
              cNomeRede := copy( cLinhaArquivo, 11, Length( cLinhaArquivo )
                 - 10 );
           end;
        if ( copy( cLinhaArquivo, 1, 3 ) = '012' ) then
           begin
              cConteudo := cConteudo + cLinhaArquivo + #13 + #10;
              cNSU := copy( cLinhaArquivo, 11, Length( cLinhaArquivo ) - 10 );
           end;
        if ( copy( cLinhaArquivo, 1, 3 ) = '027' ) then
           cConteudo := cConteudo + cLinhaArquivo + #13 + #10;
         if ( copy( cLinhaArquivo, 1, 3 ) = '999' ) then
           cConteudo := cConteudo + cLinhaArquivo;
     end;
   CloseFile( cArquivo );
   cConteudo := '000-000 = NCN' + #13 + #10 + cConteudo;
   AssignFile( cArquivo, 'INTPOS.001' );
   ReWrite( cArquivo );
   WriteLn( cArquivo, cConteudo );
   CloseFile( cArquivo );
   CopyFile( pchar( 'INTPOS.001' ), pchar( 'C:\TEF_DIAL\REQ\INTPOS.001' ),
      lFlag );
   DeleteFile( 'INTPOS.001' );
   if ( FileExists( 'C:\TEF_DIAL\RESP\INTPOS.STS' ) ) then
      DeleteFile( 'C:\TEF_DIAL\RESP\INTPOS.STS' );
   if ( FileExists( 'C:\TEF_DIAL\RESP\INTPOS.001' ) ) then
      DeleteFile( 'C:\TEF_DIAL\RESP\INTPOS.001' );

  // Se o arquivo TEF.TXT, que identifica que houve uma transação impressa
   // existir, o mesmo será exluído.
   if ( FileExists( 'TEF.TXT' ) ) then
     DeleteFile( 'TEF.TXT' );

   Application.MessageBox( pchar( 'Cancelada a Transação' + #13 + #13 +
     'Rede: ' + cNomeRede + #13 + 'Doc Nº: ' + cNSU + #13 + 'Valor: ' +
     FormatFloat( '#,##0.00', StrToFloat( cValor ) / 100 ) ), 'Atenção',
     MB_IconInformation + MB_OK );
end;

TEF - Tratando a situação de falta de comunicação com o ECF

Nesta parte, vamos desenvolver as rotinas de tratamento de erro de comunicação com a impressora, onde estaremos utilizando parte das rotinas anteriores (funções ImprimeTEF e ImprimeGerencial), apenas destacando as implementações do tratamento e, em anexo, seguirão os códigos completos destas duas funções, em Delphi e Visual Basic.

- Exemplo em Delphi

procedure TfrmPrincipal.cmdVendaCupomTEFClick(Sender: TObject);
var cCodigoProduto, cDescricaoProduto, cAliquota, cTipoQtde,
   cQtde, cTipoDesconto, cValorItem, cValorDesconto,
   cAcrescimoDesconto, cTipoAcrescimoDesconto,
   cValorAcrescimoDesconto, cFormaPGTO, cMSGPromocional,
   cValorPago, cNumeroCupom, cSaltaLinha: string;
   iTEF: integer;
   cIdentificacao: TDateTime;
begin
 // Abre Cupom Fiscal, Vende o Item e Fecha Cupom Fiscal
 iRetorno := Bematech_FI_AbreCupom( pchar( '' ) );
 if ( VerificaRetornoFuncaoImpressora( iRetorno ) ) then
    begin cCodigoProduto := '1234567890123';
          cDescricaoProduto := 'Teste de Venda de Item...';
          cAliquota := 'II'; cTipoQtde := 'I'; cQtde := '1';
          cValorItem := '1,00'; cTipoDesconto := '%';
          cValorDesconto := '00,00';
          iRetorno := Bematech_FI_VendeItem( pchar( cCodigoProduto ),
             pchar( cDescricaoProduto ), pchar( cAliquota ),
             pchar( cTipoQtde ), pchar( cQtde ), 2, pchar( cValorItem ),
             pchar( cTipoDesconto ), pchar( cValorDesconto ) );
          if ( VerificaRetornoFuncaoImpressora( iRetorno ) ) then
             begin
                cAcrescimoDesconto := 'A';
                cTipoAcrescimoDesconto := '%';
                cValorAcrescimoDesconto := '00,00';
                iRetorno := Bematech_FI_IniciaFechamentoCupom(
                   pchar( cAcrescimoDesconto ),
                   pchar( cTipoAcrescimoDesconto ),
                   pchar( cValorAcrescimoDesconto ) );
                if ( VerificaRetornoFuncaoImpressora( iRetorno ) ) then
                   begin
                      cFormaPGTO := 'Cartao Credito';
                      cValorPago := '1,00';
                      SetLength( cNumeroCupom, 6 );
                      iRetorno := Bematech_FI_NumeroCupom( cNumeroCupom );
                      VerificaRetornoFuncaoImpressora( iRetorno );
                      cIdentificacao := Time;
                      iTEF := RealizaTransacao( cIdentificacao,
                         cNumeroCupom, FormatFloat( cValorPago, 0 ) );
                      if ( iTEF = 1 ) then
                         begin iRetorno := Bematech_FI_EfetuaFormaPagamento(
                            pchar( cFormaPGTO ), pchar( cValorPago ) );
                         if ( VerificaRetornoFuncaoImpressora( iRetorno ) )
                            then
                            begin
                               cMSGPromocional := 'Obrigado, volte sempre !!!';
                               iRetorno := Bematech_FI_TerminaFechamentoCupom(
                                  pchar( cMSGPromocional ) );
                               VerificaRetornoFuncaoImpressora( iRetorno );
                               if not ( ImprimeTransacao( cFormaPGTO,
                                  cValorPago, cNumeroCupom,
                                  cIdentificacao ) ) then
                                  NaoConfirmaTransacao
                               else
                                  ConfirmaTransacao;
                            end;
                         end;
                      if ( iTEF = -1 ) then
                         Application.MessageBox(
                         'Gerencial Padrão não está ativo !', 'Atenção',
                         MB_IconError + MB_OK );
                      // Se a transação não for aprovada, deve-se permitir
                      // a escolha de outra forma de pagamento. Neste caso,
                      // está sendo utilizado "Dinheiro" como exemplo.
                      if ( iTEF = -2 ) or ( iTEF = 0 ) then
                         begin
                            cFormaPGTO := 'Dinheiro';
                            iRetorno := Bematech_FI_EfetuaFormaPagamento(
                            pchar( cFormaPGTO ), pchar( cValorPago ) );
                            if ( VerificaRetornoFuncaoImpressora( iRetorno ) )
                            then
                               begin
                                  cMSGPromocional :=
                                     'Obrigado, volte sempre !!!';
                                  iRetorno :=
                                     Bematech_FI_TerminaFechamentoCupom(
                                     pchar( cMSGPromocional ) );
                                     VerificaRetornoFuncaoImpressora(
                                        iRetorno );
                               end;
                         end;
                   end;
             end;
    end;
end;

////////////////////////////////////////////////////////////////////////////////
// Função: ImprimeTransacao
// Objetivo: Realiza a impressão da Transação TEF
// Parâmetros: string para a Forma de Pagamento
//             string para a Valor da Forma de Pagamento
//             string para o Número do Cupom Fiscal (COO)
//             TDateTime para identificar o número da transação
// Retorno: True para OK ou False para não OK
//////////////////////////////////////////////////////////////////////////////// function ImprimeTransacao( cFormaPGTO: string; cValorPago: string; cCOO: string;
 cIdentificacao: TDateTime ): boolean;
var cLinhaArquivo, cLinha, cSaltaLinha, cConteudo: string; cMensagem: TForm;
   cArquivo : TextFile; iVezes : integer;
begin
 // Bloqueia o teclado e o mouse para a impressão do TEF
 iRetorno := Bematech_FI_IniciaModoTEF();
 result := true;
 if FileExists( 'IMPRIME.TXT') then
    begin
       iRetorno := Bematech_FI_AbreComprovanteNaoFiscalVinculado( pchar(
          cFormaPGTO ), pchar( cValorPago ), pchar( cCOO ) );
       VerificaRetornoFuncaoImpressora( iRetorno )
    end;
    AssignFile( cArquivo, 'IMPRIME.TXT' );
    begin
       Reset( cArquivo );
       cConteudo := '';
       cLinha := '';
       while not EOF( cArquivo ) do
          begin
             ReadLn( cArquivo, cLinha );
             cConteudo := cConteudo + cLinha + #13 + #10;
             iRetorno := Bematech_FI_UsaComprovanteNaoFiscalVinculado( pchar(
                cLinha ) + #13 );

             // Aqui é feito o tratamento de erro de comunicação com a
             // impressora (desligamento da impressora durante a impressão do
             // comprovante).

             if not ( VerificaRetornoFuncaoImpressora( iRetorno ) ) then
                begin
                   iRetorno := Bematech_FI_FinalizaModoTEF();
                   if ( Application.MessageBox( 'A impressora não responde!' +
                      #13 + 'Deseja imprimir novamente?', 'Atenção',
                      MB_IconInformation + MB_YESNO ) = IDYES ) then
                   begin
                      CloseFile( cArquivo );
                      iRetorno:=Bematech_FI_FechaComprovanteNaoFiscalVinculado;
                      if ( ImprimeGerencial = 1 ) then
                         begin
                            result := true; exit;
                         end
                      else
                         begin
                            result := false; exit;
                         end;
                   end
                   else
                   begin
                   CloseFile( cArquivo );
                   iRetorno := Bematech_FI_FechaComprovanteNaoFiscalVinculado;
                   result := false; exit;
                   end;
                end
             else
                if EOF( cArquivo ) then
                   begin
                      .
                      .
                      .

////////////////////////////////////////////////////////////////////////////////
// Função: ImprimeGerencial
// Objetivo: Imprimir através do Relatório Gerencial a transação efetuada.
// Retorno: 1 para OK ou diferente de 1 para não OK
////////////////////////////////////////////////////////////////////////////////
function ImprimeGerencial: integer;
var cConteudo, cLinha, cSaltaLinha, cLinhaArquivo: string;
   cArquivo : TextFile;
  iTentativas, iVezes: integer;
  cMensagem : TForm;
  bTransacao: boolean;
begin
  if FileExists( 'IMPRIME.TXT') then
     DeleteFile( 'IMPRIME.TXT' );

  result := 1;
  for iTentativas := 1 to 7 do
     begin
       .
       .
       .
  // Bloqueia o teclado e o mouse para a impressão do TEF
  iRetorno := Bematech_FI_IniciaModoTEF();
 if FileExists( 'IMPRIME.TXT') then
     begin
       AssignFile( cArquivo, 'IMPRIME.TXT' );
       Reset( cArquivo );
       cConteudo := '';
       cLinha := '';
       while not EOF( cArquivo ) do
         begin
           ReadLn( cArquivo, cLinha );
           cConteudo := cConteudo + cLinha + #13 + #10;
           iRetorno := Bematech_FI_RelatorioGerencial( pchar( cLinha )
             + #13 );

           // Aqui é feito o tratamento de erro de comunicação com a impressora
           // (desligamento da impressora durante a impressão do comprovante).

           if not ( VerificaRetornoFuncaoImpressora( iRetorno ) ) then
             begin
               iRetorno := Bematech_FI_FinalizaModoTEF();
               if ( Application.MessageBox( 'A impressora não responde!' +
                 #13 + 'Deseja imprimir novamente?', 'Atenção',
                 MB_IconInformation + MB_YESNO ) = IDYES ) then
                 begin
                   CloseFile( cArquivo );
                   iRetorno := Bematech_FI_FechaRelatorioGerencial;
                   ImprimeGerencial;
                   exit;
                 end
               else
                 begin
                   CloseFile( cArquivo );
                   iRetorno := Bematech_FI_FechaRelatorioGerencial;
                   result := 0;
                   exit;
                 end;
             end;
            .
             .
             .