quinta-feira, 6 de janeiro de 2011

Checagem de CEP por Estado

Verifica se um CEP é valido ou não, passando o Estado e o Cep como parâmetro.



function ChecaCEP(cCep:String ; cEstado:String): Boolean;
var
cCEP1 : Integer;
begin
cCep := copy(cCep,1,5) + copy(cCep,7,3);
cCEP1 := StrToInt(copy(cCep,1,3));
if Length(trim(cCep)) > 0 then
   begin
   if (StrToInt(cCep) <= 1000000.0) then
       begin
       MessageDlg('CEP tem que ser maior que [01000-000]',mtError,[mbOk],0);
       Result := False
       end
   else
   begin
     if Length(trim(copy(cCep,6,3))) < 3 then Result := False else
     if (cEstado = 'SP') and (cCEP1 >= 10 ) and (cCEP1 <= 199) then Result := True else
     if (cEstado = 'RJ') and (cCEP1 >= 200) and (cCEP1 <= 289) then Result := True else
     if (cEstado = 'ES') and (cCEP1 >= 290) and (cCEP1 <= 299) then Result := True else
     if (cEstado = 'MG') and (cCEP1 >= 300) and (cCEP1 <= 399) then Result := True else
     if (cEstado = 'BA') and (cCEP1 >= 400) and (cCEP1 <= 489) then Result := True else
     if (cEstado = 'SE') and (cCEP1 >= 490) and (cCEP1 <= 499) then Result := True else
     if (cEstado = 'PE') and (cCEP1 >= 500) and (cCEP1 <= 569) then Result := True else
     if (cEstado = 'AL') and (cCEP1 >= 570) and (cCEP1 <= 579) then Result := True else
     if (cEstado = 'PB') and (cCEP1 >= 580) and (cCEP1 <= 589) then Result := True else
     if (cEstado = 'RN') and (cCEP1 >= 590) and (cCEP1 <= 599) then Result := True else
     if (cEstado = 'CE') and (cCEP1 >= 600) and (cCEP1 <= 639) then Result := True else
     if (cEstado = 'PI') and (cCEP1 >= 640) and (cCEP1 <= 649) then Result := True else
     if (cEstado = 'MA') and (cCEP1 >= 650) and (cCEP1 <= 659) then Result := True else
     if (cEstado = 'PA') and (cCEP1 >= 660) and (cCEP1 <= 688) then Result := True else
     if (cEstado = 'AM') and ((cCEP1 >= 690) and (cCEP1 <= 692) or (cCEP1 >= 694) and 
(cCEP1 <= 698)) then Result := True else
     if (cEstado = 'AP') and (cCEP1 = 689) then Result := True else
     if (cEstado = 'RR') and (cCEP1 = 693) then Result := True else
     if (cEstado = 'AC') and (cCEP1 = 699) then Result := True else
     if ((cEstado = 'DF') or (cEstado = 'GO')) and (cCEP1 >= 700)and(cCEP1 <= 769)then 
Result := True else
     if (cEstado = 'TO') and (cCEP1 >= 770) and (cCEP1 <= 779) then Result := True else
     if (cEstado = 'MT') and (cCEP1 >= 780) and (cCEP1 <= 788) then Result := True else
     if (cEstado = 'MS') and (cCEP1 >= 790) and (cCEP1 <= 799) then Result := True else
     if (cEstado = 'RO') and (cCEP1 = 789) then Result := True else
     if (cEstado = 'PR') and (cCEP1 >= 800) and (cCEP1 <= 879) then Result := True else
     if (cEstado = 'SC') and (cCEP1 >= 880) and (cCEP1 <= 899) then Result := True else
     if (cEstado = 'RS') and (cCEP1 >= 900) and (cCEP1 <= 999) then Result := True else
Result := False
   end;
 end
else
   begin
   Result := True;
   end
end;

Controle sobre a digitação

Quando alguém esta  digitando  algum valor que posteriormente será utilizado para calculo alguns cuidados são necessários, esse procedimento  ValidaKey  deve ser ligado no OnChange do TDBEdit para checar qual foi a tecla digitada.

procedure ValidaKey(Const Sender:TObject; var key: char);
begin
       if not(key in ['0'..'9','.',',',#8,#13]) then key := #0;
       if key in [',','.'] then key := DecimalSeparator;
       if key = DecimalSeparator then
                  if pos(key,TEdit(Sender).Text) <> 0 then key := #0;
end;


       if not(key in ['0'..'9','.',',',#8,#13]) then key := #0;

Se algum numero, ponto, virgula, BackSpace ou Enter for digitado então pode passar normalmente, caso contrario a tecla pressionada é ignorada.

       if key in [',','.'] then key := DecimalSeparator;

Se ponto ou virgula, assume como separador decimal.

        if key = DecimalSeparator then
          if pos(key,TEdit(Sender).Text) <> 0 then key := #0;

O separador decimal so pode ser digitado uma unica vez, na tentativa de uma segunda digitação ignora-se o símbolo.

Observem que o mais importante aqui é o conceito utilizado, o fato de se interceptar os caracteres digitados pelo usuário e poder filtrar esses caracteres para evitar uma entrada de  dados inconsistente. O exemplo de numero e símbolos não é conclusivo, uma vez que o mesmo efeito poderia ter sido obtido com a aplicação de uma mascara.

Obtendo as informações de versão dos arquivos

Um dos recursos disponibilizados pelo Delphi é a customização das informações de versão a serem "anexadas" na linkagem.
Pouco utilizado, este recurso é muito interessante, pois possibilita o cadastro de diversas informações sobre o arquivo gerado, como: número de versão, nome do produto, nome interno do arquivo, nome da empresa, etc.

Podemos alterar as informações na página "Version Info", da página "Project Options":

Atenção com o item "Auto-increment build number": ele só será incrementado automaticamente quando for executada a opção "Build All" para compilar o projeto.
Porém, não existem rotinas "prontas" para obtermos estas informações. É necessário fazermos chamadas diretamente a API Win32, mais espeficamente, para as funções como a "GetFileVersionInfo" e a "VerQueryValue".
Abaixo encontramos uma função, a "FileVerInfo", que exemplifica o processo de obtenção das informações. Ela irá retornar "True" caso o arquivo informado no parâmetro "FileName" possuir as informações de versão, e devolverá por referência um "TStringList" contendo as informações.


//Código

function FileVerInfo(const FileName: string; var FileInfo: TStringList): Boolean;
const
    Key: array[1..9] of string =('CompanyName', 'FileDescription', 'FileVersion', 'InternalName', 'LegalCopyright', 'OriginalFilename', 'ProductName', 'ProductVersion', 'Comments');
KeyBr: array [1..9] of string = ('Empresa', 'Descricao', 'Versao do Arquivo', 'Nome Interno', 'Copyright', 'Nome Original do Arquivo', 'Produto', 'Versao do Produto', 'Comentarios');
var
Dummy : THandle;
BufferSize, Len : Integer;
Buffer : PChar;
LoCharSet, HiCharSet : Word;
Translate, Return : Pointer;
StrFileInfo, Flags : string;
TargetOS, TypeArq : string;
FixedFileInfo : Pointer;
i : Byte;

begin
Result := False;
{ Obtemos o tamanho em bytes do "version  information" }
BufferSize := GetFileVersionInfoSize(PChar(FileName), Dummy);
if BufferSize <> 0 then
begin
   GetMem(Buffer, Succ(BufferSize));
   try
     if GetFileVersionInfo(PChar(FileName), 0, BufferSize,
       Buffer) then
     { Executamos a função "VerQueryValue" e conseguimos informações sobre o idioma /character-set }
     if VerQueryValue(Buffer, '\VarFileInfo\Translation', Translate, UINT(Len)) then
     begin
       LoCharSet := LoWord(Longint(Translate^));
       HiCharSet := HiWord(Longint(Translate^));
       for i := 1 to 9 do
       begin
         { Montamos a string de pesquisa }
         StrFileInfo := Format('\StringFileInfo\0%x0%x\%s', [LoCharSet, HiCharSet, Key[i]]);
         { Adicionamos cada key pré-definido }
         if VerQueryValue(Buffer,PChar(StrFileInfo), Return, UINT(Len)) then
         FileInfo.Add(KeyBr[i] + ': ' + PChar(Return));
       end;
       if VerQueryValue(Buffer,'\',FixedFileInfo, UINT(Len))
         then
         with TVSFixedFileInfo(FixedFileInfo^) do
       begin
         Flags := '';
         {Efetuamos um bitmask e obtemos os "flags" do arquivo}
       if (dwFileFlags and VS_FF_DEBUG) = VS_FF_DEBUG then
           Flags := Concat(Flags,'*Debug* ');
       if (dwFileFlags and VS_FF_SPECIALBUILD) = VS_FF_SPECIALBUILD then
                Flags := Concat(Flags, '*Special Build* ');
       if (dwFileFlags and VS_FF_PRIVATEBUILD) = VS_FF_PRIVATEBUILD then
                Flags := Concat(Flags, '*Private Build* ');
       if (dwFileFlags and VS_FF_PRERELEASE) = VS_FF_PRERELEASE then
                Flags := Concat(Flags, '*Pre-Release Build* ');
       if (dwFileFlags and VS_FF_PATCHED) = VS_FF_PATCHED then
                 Flags := Concat(Flags, '*Patched* ');
       if Flags <> '' then FileInfo.Add('Atributos: ' + Flags);
       TargetOS := 'Plataforma (OS): ';
       { Plataforma }
       case dwFileOS of
         VOS_UNKNOWN :
           TargetOS := Concat(TargetOS, 'Desconhecido');
         VOS_DOS :
           TargetOS := Concat(TargetOS, 'MS-DOS');
         VOS_OS216 :
           TargetOS := Concat(TargetOS, '16-bit OS/2');
         VOS_OS232 :
           TargetOS := Concat(TargetOS, '32-bit OS/2');
         VOS_NT    :
           TargetOS := Concat(TargetOS, 'Windows NT');
         VOS_NT_WINDOWS32, 4:
           TargetOS := Concat(TargetOS, 'Win32 API');
         VOS_DOS_WINDOWS16:
           TargetOS := Concat(TargetOS, '16-bit Windows ',
           'sob MS-DOS');
         else
            TargetOS := Concat(TargetOS, 'Fora do Padrão. Código: ', IntToStr(dwFileOS));
      end;

       FileInfo.Add(TargetOS);
       TypeArq := 'Tipo de Arquivo: ';
       { Tipo de Arquivo }
       case dwFileType of
         VFT_UNKNOWN :
           TypeArq := Concat(TypeArq,'Desconhecido');
         VFT_APP : TypeArq := Concat(TypeArq,'Aplicacao');
         VFT_DLL : TypeArq := Concat(TypeArq,'Dynamic-Link Lib.');
         VFT_DRV : begin
           TypeArq := Concat(TypeArq,'Device driver - Driver ');
           case dwFileSubtype of VFT2_UNKNOWN : TypeArq := Concat (TypeArq, 'Desconhecido');
             VFT2_DRV_PRINTER : TypeArq := Concat(TypeArq,'de Impressao');
             VFT2_DRV_KEYBOARD : TypeArq := Concat(TypeArq,'de Teclado');
             VFT2_DRV_LANGUAGE : TypeArq := Concat(TypeArq,'de Idioma');
             VFT2_DRV_DISPLAY : TypeArq := Concat(TypeArq,'de Vídeo');
             VFT2_DRV_MOUSE : TypeArq := Concat(TypeArq,'de Mouse');
             VFT2_DRV_NETWORK : TypeArq := Concat(TypeArq,'de Rede');
             VFT2_DRV_SYSTEM : TypeArq := Concat(TypeArq,'de Sistema');
             VFT2_DRV_INSTALLABLE : TypeArq := Concat(TypeArq,'Instalavel');
             VFT2_DRV_SOUND : TypeArq := Concat(TypeArq,'Multimida');
           end;
         end;
         VFT_FONT : begin
           TypeArq := Concat(TypeArq,'Fonte - Fonte ');
           case dwFileSubtype of VFT2_UNKNOWN : TypeArq := Concat(TypeArq,  'Desconhecida');
             VFT2_FONT_RASTER : TypeArq := Concat(TypeArq,'Raster');
             VFT2_FONT_VECTOR : TypeArq := Concat(TypeArq,'Vetorial');
             VFT2_FONT_TRUETYPE : TypeArq := Concat(TypeArq,'TrueType');
           end;
         end;
         VFT_VXD : TypeArq := Concat(TypeArq,'Virtual Device');
         VFT_STATIC_LIB
           : TypeArq := Concat(TypeArq,'Static-Link Lib.');
       end;
       FileInfo.Add(TypeArq);
     end;
   end;
   finally
     FreeMem(Buffer, Succ(BufferSize));
     Result := FileInfo.Text <> '';
   end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  StrLst: TStringList;
begin
StrLst := TStringList.Create;
try
   FileVerInfo('C:\WINDOWS\SYSTEM\TAPI.DLL', StrLst);
   Memo1.Lines.Assign(StrLst);
finally
   StrLst.Free;
end;
end;

quarta-feira, 5 de janeiro de 2011

O que são componentes?

A livraria visual de componentes (VCL).
Um componente, em sua definição mais simples não é mais que um objeto descendente do tipo TComponent. Todos os componentes descendem na sua forma mais primitiva de TComponent, já que TComponent proporciona as características básicas que todo componente deve ter: capacidade de ser mostrado na paleta de componentes assim como de operar a nível de desenho de formulário.
Os componentes tornam fácil a programação em Delphi. Em vez de ter que operar a nível de unidades, o usuário de um componente simplesmente tem que colocar na posição desejada no seu form. Isso é tudo: o Delphi se encarrega do resto.
Todos os componentes formam parte da Hierarquia de objetos denominada Visual Component Library (VCL). Quando se cria um novo componente, este se deriva a partir de um componente existente (bem como TComponent ou algum outro mais especializado) e se junta a VCL.
Anatomia de um componente.
Propriedades, métodos e eventos.
Como já mencionado, um componente é um objeto, e como tal, consta de código e dados. Mas ao referirmos a estes não utilizaremos estos termos, só que falaremos de propriedades e métodos, assim como de eventos. A longo do curso iremos estudando em profundidade todos estes aspectos, mas teremos agora uma primeira aproximação:
Propriedades
As propriedades proporcionam ao usuário do componente um fácil acesso ao mesmo. Ao mesmo tempo, permite ao programador do componente "esconder" a estrutura de dados subjacente. Entre as vantagens de utilizar propriedades para usar o componente se podem citar:
As propriedades estão disponíveis em tempo de desenho. Deste modo o usuário do componente pode iniciar os valores das propriedades sem necessidade de escrever uma só linha de código.
As propriedades permitem a validação dos dados ao mesmo tempo de ser introduzidas. Assim se podem prevenir erros causados por valores inválidos.
Nos asseguram que desde o primeiro momento nossas propriedades tenham um valor válido, evitando o erro comum de fazer referência a uma variável que não tenha sido convenientemente iniciada.
Eventos
Os eventos são as conexões existentes entre um determinado evento e ao código escrito pelo programador de componentes. Assim por exemplo, quando ao evento clique do Mouse se poderia mostrar uma mensagem. Ao código que se executa quando se produz um determinado evento se denomina controlador de eventos (event handler) e normalmente é o próprio usuário do componente quem o escreve. Os eventos mais comuns já formam parte dos próprios componentes do Delphi (ações do Mouse, pressionamento do teclado...), mas é também possível definir novos eventos.
Métodos
Os métodos são os procedimentos e/ou funções que formam parte do componente. O usuário do componente os utiliza para realizar uma determinada ação ou para obter um valor determinado que não se pode acessar por meio de uma propriedade. Já que requerem execução de código, os métodos só estão disponíveis em tempo de execução.
Controle de acesso a um componente.
Declarações privadas, protegidas, públicas e publicadas.
Object Pacal dispõe de quatro níveis de controle de acesso para os campos, propriedades e métodos de um componente. Este controle de acesso permite especificar ao programador do componentes que parte do código pode acessar a que partes do objeto. Deste modo se define a interface do componente. É importante planejar bem esta interface, já que assim nossos componentes serão facilmente programáveis e reutilizáveis.
Ao menos que se especifique o contrário, os campos, propriedades e métodos que se unem a um objeto são do tipo publicados (published). Todos os níveis de controle de acesso operam a nível de unidades, é decidir se uma parte dum objeto é acessível ou não, em uma parte da unidade, é também acessível (ou não) em qualquer outra parte da unidade.
Privado: ocultando os detalhes de implementação
Declarando uma parte de um componente (bem como um campo, propriedade ou método) privado (private) provoca que essa parte do objeto seja invisível ao código externo a unidade na qual se declara o objeto. Dentro da unidade que contem a declaração, o código pode acessar a essa parte do objeto como se fosse público.
A principal utilidade das declarações privadas é que permitem ocultar os detalhes de implementação do componente ao usuário final do mesmo, já que estes não podem acessar a parte privada de um objeto. Deste modo se pode trocar a implementação interna do objeto sem afetar o código que havia escrito ao usuário.
Protegido: definindo a interface do programador.
Declarar uma parte de um componente como protegido (protected) provoca, o mesmo se declarado privado, que ao código externo a unidade não pode acessar a dita parte (se faz oculta ao código externo a a unidade). A diferença principal entre declarar uma parte de um objeto protegido ou privado é que os descendentes do componente podem fazer referência a essa parte.
Este comportamento é especialmente útil para a criação de componentes que vão se descender daquilo que criamos.
Público: definindo a interface em tempo de execução.
Todas partes de um objeto que declaremos públicas (public) poderiam ser referidas por qualquer código seja interno ou externo a própria unidade. Neste sentido, a parte pública identifica a interface em tempo de execução de nosso componente. Os métodos que o usuário do componente deve chamar devem ser declarados públicos, assim como também as propriedades de somente leitura, são somente válidas em tempo de execução.
As propriedades declaradas públicas não aparecerão no inspetor de objetos.
Esta seção é talvez a mais importante a considerar ao desenhar um componente. Quando se desenham componentes, se deve considerar cuidadosamente que métodos e propriedades devem ser públicas. Se o desenho é correto, este permitira retocar as estruturas de dados e métodos internos do componente sem ter que tocar a interface pública, que seguirá sendo a mesma para o usuário do componente.
Publicado: definindo a interface em tempo de desenho.
Ao declarar parte de um objeto publicado (published) ocorre que a parte pública e ademais gera informações em tempo de execução para dita parte. As propriedades declaradas publicadas aparecem no inspetor de objetos em tempo de desenho. E já que somente as partes publicadas aparecem no inspetor de objetos, estas partes definem a interface em tempo de desenho do nosso componente. Em geral somente se devem declarar publicadas propriedades e não funções ou procedimentos.
Passos necessários para criar um componente.
O criador de componentes.
Os passos necessários para criar um novo componente são os seguintes:
1. Criar uma unidade para o novo componente.
2. Derivar o novo componente a partir de outro existente, o qual servirá de base para as novas características desejadas.
3. Estabelecer as propriedades, eventos e métodos necessários ao novo componente.
4. Registrar o componente, incluindo os bitmaps adicionais, arquivos de ajuda, etc.
5. Instalar o novo componente na paleta de componentes.
De todos os passos citados, há um que é especialmente importante: a eleição do ascendente a partir da qual derivar o novo componente. Este passo é crucial, já que uma boa eleição do ascendente pode fazer a tarefa de criar novas propriedades e métodos realmente fácil. Como base para a eleição do ascendente, convém fazer notar as seguintes normas:
TComponent - O ponto de partida para os componentes não visuais.
TWinControl - O ponto de partida se é necessário que o componente disponha de handles.
TGraphicControl - Um bom ponto de partida para componentes visuais que não seja necessário que disponham de handles, posso dizer, que não recebam o foco. Esta classe dispõe do método Paint e de Canvas.
TCustomControl - O ponto de partida mais comum. Esta classe dispõe de window handle, eventos e propriedades comuns e, principalmente, canvas com o método Paint.
Bom, já sabemos como determinar o ponto de partida. Vejamos agora como criar a unidade que abrigará o componente. Há duas opções, criar a unidade manualmente ou deixar que o Delphi faça o trabalho "sozinho" utilizando o experto de componentes. Se optarmos pela primeira solução, basta dar um click em New Unit e poremos mãos a obra, mas deste modo teremos que fazer tudo manualmente: derivar o novo componente, registrá-lo, etc. Por isso é mais recomendável a segunda opção: utilizar o experto de componentes.
Para abrir o experto de componentes basta escolher File|New Component.
Aparecerá um quadro de diálogo que devemos complementar os seguintes campos:
Class Name: Aqui devemos especificar o nome do novo componente.
Ancestor type: Introduziremos aqui o ascendente a partir do qual derivaremos nosso componente.
Palette Page: Indicaremos aqui a página da paleta na qual queremos que apareça o novo componente.
Uma vez introduzidos estes campos, clique em Ok para que seja criado o código de nossa unidade. Se por exemplo termos introduzido os seguintes dados no experto de componentes:
Class Name: TMiComponente
Ancestor Type: TComponent
Palette Page: Curso
Ao clicar em Aceitar, Delphi geraria a seguinte unidade, pronta para introduzir as propriedades e métodos de nosso componente:
unit Unit1;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs;
type
TMiComponente = class(TComponent)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents( 'Curso', [TMiComponente]);
end;
end.
A partir daqui tudo consiste em introduzir as propriedades e métodos necessários para o funcionamento do nosso componente. Mas antes de nada convém fazer notar alguns aspectos:
Na clausula uses, Delphi originalmente as unidades standard. Se nosso componente não usa alguma delas podemos eliminá-la de dita clausula. Do mesmo modo, se utilizarmos algum procedimento ou função situado em outra unidade, devemos citar a dita unidade na clausula uses.
As declarações das propriedades, campos e métodos que vamos definindo, as citaremos na seção apropriada que corresponda, é decidir se as declararemos privadas, protegidas, pública o publicadas.
Delphi declara e define automaticamente o procedimento Register para registrar o componente na paleta.

terça-feira, 4 de janeiro de 2011

TEF - Realizando uma venda com mais de uma transação

Chegamos ao final de nosso pequeno treinamento de TEF! Conseguimos visualizar as principais rotinas e métodos, utilizadas durante o desenvolvimento das operações com o TEF.
Nesta última parte, estaremos conhecendo como uma transação com mais de um cartão é realizada.
Iremos passar por alguns procedimentos importantes e estaremos visualizando um fluxo básico de uma transação.
Então, vamos lá! E, uma boa leitura!
 
1) Procedimentos de uma operação TEF com múltiplos cartões
1.1) A aplicação imprimirá o cupom fiscal normalmente, até a sua totalização;
1.2) Enviará uma solicitação de transação TEF com os dados respectivos. Você deverá salvar uma cópia de cada arquivo de resposta "Intpos.001", pois você precisará dos dados para cancelar a transação, se necessário (quando houver uma queda de energia ou falta de comunicação com a impressora);
Observação: Caso exista uma nova transação TEF, a primeira deverá ser confirmada (CNF).
1.3) Abrirá o arquivo de resposta "Intpos.001" para verificar se o campo "001-000" é igual ao enviado na solicitação, caso contrário, deverá excluir esse arquivo e aguardar o próximo;
1.4) Analisará o campo "009-000". Se a transação for aprovada deverá efetuar a forma de pagamento. Se a transação não for aprovada, deverá exibir a mensagem do campo "030-000" ao operador e aguardar o seu "OK";
1.5) Antes de enviar a solicitação para a segunda transação, a aplicação deverá confirmar (CNF) a transação anterior, sem imprimi-la. O cupom fiscal deverá permanecer aberto (totalizado) após esta confirmação, aguardando o próximo pagamento;
1.6) Enviará a solicitação da segunda transação TEF com os dados respectivos. Você deverá salvar uma cópia de cada arquivo de resposta "Intpos.001", pois você precisará dos dados para cancelar a transação, se necessário (quando houver uma queda de energia ou falta de comunicação com a impressora);
1.7) Repetir o passo 1.4;
1.8) Repetir o 1.5;
Observação: Repetir os passos de 1.5 a 1.8 para cada nova transação.
1.9) Quando a aplicação chegar à última transação TEF, esta não deverá ser confirmada;
1.10) A aplicação encerrará o cupom fiscal com as formas de pagamento, respectivas a cada transação, e iniciará as impressões dos comprovantes do TEF (2 vias para cada);
1.11) Após a impressão da última transação TEF, esta deverá então ser confirmada (CNF), finalizando todo processo;
Observação: Tanto o teclado quanto o mouse deverão permanecer bloqueados durante as impressões.
1.12) Os arquivos temporários deverão ser excluídos.
Dica: As formas de pagamento usadas para realizar transação com TEF, deverão ser as últimas no fechamento do cupom fiscal. Por exemplo, se o cupom fiscal for pago com 3 formas de pagamento diferentes "Dinheiro", "Cheque" e "Cartão", a forma "Cartão" deverá ser a última.
2) Procedimentos com falta de comunicação com o ECF
2.1) Se durante a impressão dos comprovantes do TEF, houver uma falta de comunicação com o ECF, a aplicação deverá detectar esta falta e exibir a seguinte mensagem ao operador: "A impressora não responde. Deseja imprimir novamente?"
2.2) Se o operador optar por "Sim", a aplicação deverá fechar o comprovante, abrir o relatório gerencial e imprimir os comprovantes de todas as transações;
2.3) Se o operador optar por "Não", a aplicação deverá enviar um NCN (Não Confirmação) referente a última transação realizada e um CNC (Cancelamento) referente as demais transações, pois estas haviam sido confirmadas anteriormente.
2.4) O CNC deverá ser enviado para cada transação que foi confirmada respeitando a seguinte lógica:
2.4.1) A aplicação enviará um CNC para a primeira transação confirmada e imprimirá o texto do "Intpos.001" de resposta (referente a este cancelamento), em um relatório gerencial.
2.4.2) A aplicação enviará um CNF (Confirmação) confirmando este cancelamento e enviará o novo CNC para a outra transação confirmada, conforme citado acima. Este processo se aplicará para todas as transações que existirem.
Observação: A aplicação deverá exibir uma mensagem ao operador com as seguintes informações: "Nome da Rede" (bandeira), "NSU" e "Valor da Transação", para cada transação cancelada, incluindo a não confirmada.
2.5) Se durante a impressão dos comprovantes de cancelamento houver novamente uma falta de comunicação com o ECF, o procedimento será o mesmo do ítem 2.1.
2.6) Se o operador optar por "Sim", a aplicação deverá fechar o relatório gerencial e abrir o novo, imprimindo todo o texto novamente.
2.7) Se o operador optar por "Não", a aplicação deverá enviar um NCN (Não Confirmação) e novamente o CNC (Cancelamento) referente à transação, imprimindo o texto do INTPOS.001 de resposta em um novo relatório gerencial.
3) Procedimentos com queda de energia
3.1) Se durante a impressão dos comprovantes do TEF, houver uma queda de energia, a aplicação deverá detectar esta queda, enviar um NCN (Não Confirmação) para a última transação e um CNC (Cancelamento) para cada transação que havia sido confirmada anteriormente.
3.2) Se durante a impressão dos comprovantes do cancelamento houver uma queda de energia, a aplicação deverá detectar esta queda, fechar o relatório gerencial pendente, enviar o NCN (Não Confirma) e novamente o CNC (Cancelamento) referente à transação, imprimindo o texto do "Intpos.001" de resposta em um novo relatório gerencial.
3.3) A aplicação deverá enviar um CNF (Confirmação) após cada impressão do comprovante de cancelamento.
4) Fluxo básico de uma transação: