Ir para conteúdo
  • Cadastre-se

Painel de líderes

Conteúdo popular

Showing content with the highest reputation on 05-02-2019 em todas as áreas

  1. Olá pessoal, Para quem ainda não conhece, o Lazarus/FPC é uma poderosa IDE e compilador da Linguagem Object Pascal, muito semelhante ao Delphi, e desenvolvido totalmente em Código Aberto... ( Saiba mais em: https://www.lazarus-ide.org/index.php?page=about ) Hoje ocorreu o lançamento da versão 2.0.0 do Lazarus... O anúncio oficial, pode ser lido no fórum do Lazarus: http://forum.lazarus-ide.org/index.php/topic,44161.0.html Essa versão ainda usa o FPC (Free Pascal Compiler), na versão 3.0.4, então não devemos ter mudanças brusca na compilação dos projetos existentes... Você pode baixar o Lazarus 2.0, na página oficial do Projeto: https://www.lazarus-ide.org/ (Observe porém, que o Download sugerido, provavelmente será de um Compilador para Windows 64... O que muitas vezes não é o desejado, para manter a compatibilidade com as diferentes versões de Windows e as DLLs existentes) Portanto, recomendo selecionar a versão 32 Bits, conforme destacado, na imagem abaixo... Se você quer realmente gerar aplicações 64 bits, ainda poderá fazer um Cross-compiling , baixando um instalador complementar em: https://sourceforge.net/projects/lazarus/files/Lazarus Windows 32 bits/Lazarus 2.0.0/ O ACBr tem um ótimo suporte ao Lazarus/FPC, isso porque a maioria dos Consultores do Projeto ACBr, usam Lazarus/FPC como principal IDE para Desenvolvimento, e todos os nosso projetos, como: ACBrMonitorPLUS, e ACBrLib, são desenvolvidos em Lazarus/FPC. Abaixo segue um Screen Shot da minha IDE de trabalho (clique para aumentar) Quer conhecer mais aplicações desenvolvidas em Lazarus ? Veja esse Link: http://wiki.freepascal.org/Lazarus_Application_Gallery
    8 pontos
  2. Instalando o FixInsight para utilizar no seu projeto Para utilizar o TMS FixInsight no seu projeto, primeiro faça o download da versão trial no site oficial. O FixInsight está disponível para todas as versões do Delphi a partir do Delphi 2006. A versão pro possui linha de comando, permitindo você executar a ferramenta mesmo quando o Delphi não está aberto. Isso permite você integrar com seu sistema de Build ou sistema de integração contínua. A instalação é muito simples, bastando escolher em qual versão do Delphi você quer instalar. Após a instalação as seguintes entradas vão aparecer no menu Project: E também no "Project Manager" (clique com botão direito no projeto): A entrada "FixInsight Settings..." configura a ferramenta e pode habilitar ou desabilitar as mensagens geradas. Ela abre uma tela como essa: Na imagem acima você pode observar que a mensagem "C101 Method '%s' is too long (%d lines)" está selecionada e permite a configuração de quantas linhas para você um método, function ou procedure não deve exceder. Dá pra ver também que as mensagens C102 e C103 estão desabilitadas e assim não geram avisos. A entrada "Run FixInsight for unit1.pas" executa a ferramenta para a unit aberta atualmente (neste caso Unit1.pas). A entrada "Run FixInsight" executa a ferramenta no projeto atual inteiro. Rodando o FixInsight no seu projeto Como mencionado, é por meio da entrada 'Run FixInsight" que você executa a ferramenta no seu projeto. Então basta abrir o seu projeto e executar por meio do menu Project -> Run FixInsight. Ele vai ser executado e abrir uma aba na janela de mensagens como na imagem abaixo. Dois cliques te jogam na unit e linha relacionada a mensagem: Agora é com você. Você analisa a mensagem o código e verifica se algo pode ser feito.
    6 pontos
  3. Foto por David Siglin em Unsplash. Olá pessoal, É bom quando encontramos uma ferramenta que facilita ou melhora nosso trabalho, não? Todos devem ter notado que ultimamente temos enviado vários commits ao SVN de remoção de warnings e hints, muitas vezes mencionando a ferramenta FixInsight. Para quem não conhece, essa ferramenta faz uma análise do seu código e aponta possíveis erros e sugere otimizações. Ela é uma ferramenta muito boa, tanto que foi comprada pela TMS e se tornou TMS FixInsight. Já tem um tempo que conheço a ferramenta e sempre tive o desejo de rodá-la em todo o código do ACBr. Mas devido ao tempo não tinha sido possível. Depois de um incentivo (valeu @Waldir Paim), eu resolvi baixar a versão trial e fazer isso. E que bom que fiz. Gostaríamos de compartilhar com vocês algumas coisas que encontramos no nosso código com a ajuda dessa ferramenta. Encontrando pequenos problemas num código gigante Vamos começar por um código que estava no ACBrValidador. Vejam esse código, onde a função ValidarCEP de baixo chama a função ValidarCEP de cima, e tente encontrar um problema: function ValidarCEP(const ACEP, AUF: String): String; begin Result := ValidarDocumento( docCEP, ACEP, AUF); end; function ValidarCEP(const ACEP: Integer; AUF: String): String; begin ValidarCEP( FormatarCEP(ACEP), AUF ); end; Conseguiu ver o problema? Essa função nunca retornaria que um CEP é inválido se você passasse o CEP como inteiro. Precisava de um “Result := ” no início. Simples? Nem tanto quando lembramos do tamanho do projeto ACBr. Temos mais de 200 componentes e mais de 779 mil linhas de código, contribuídos por dezenas ou talvez centenas de programadores, embora a nossa equipe de commiters seja realmente pequena. Só a unit ACBrValidador.pas em questão tem atualmente cerca de 2070 linhas. Não fica muito mais fácil quando uma ferramenta aponta pra você? [FixInsight Warning] ACBrValidador.pas(294): W521 Return value of function 'ValidarCEP' might be undefined Vamos a outro exemplo no pacote ACBrSerial, componente ACBrECF: [FixInsight Warning] ACBrECFDaruma.pas(4638): W503 Assignment right hand side is equal to its left hand side Veja o código (só a parte interessante): else if StrToIntDef(fsNumVersao, -1) >= 345 then begin RetCmd := EnviaComando( ESC + #240 ); RetCmd := Copy(RetCmd, 92, Length(RetCmd)); RetCmd := RetCmd; //<--- Viu aqui??? for A := 0 to fpAliquotas.Count-1 do begin fpAliquotas[A].Total := RoundTo( StrToFloatDef(Copy(RetCmd,(A*14)+1,14),0) / 100, -2 ); end; end; end; Uma linha que não faz absolutamente nada a não ser gastar espaço, memória e CPU. Uma linha desnecessária a menos no código. E você consegue encontrar um no seu aplicativo código que nunca será executado? Ainda no mesmo pacote, veja esse exemplo:  [FixInsight Warning] ACBrECFDataRegis.pas(1838): W509 Unreachable code Nesse código: if (fsArqPrgBcoTXT <> '') and (not FileExists( fsArqPrgBcoTXT )) then begin Msg := ACBrStr( 'Arquivo '+fsArqPrgBcoTXT+' não encontrado. '+ 'Valores padrões serão utilizados.' ) ; raise EACBrECFErro.Create( Msg ); fsArqPrgBcoTXT := '' ; //Essa linha nunca vai ser executada porque tem um raise acima. end ; Mais uma vez, tente imaginar procurar esse problema num projeto tão grande. Não é facilmente percebido se você não tiver olhos treinados e estiver procurando problemas. Vamos a outro exemplo ainda no componente ACBrECF:  [FixInsight Warning] ACBrECFEscECF.pas(1222): W517 Variable 'CHK' hides a class field, method or property Veja esse código: procedure TACBrECFEscECFResposta.SetResposta(const AValue: AnsiString); Var Soma, I, F, LenCmd : Integer ; CHK : Byte ; begin O problema desse código é que ele confunde uma variável local (CHK) com uma propriedade da classe (TACBrECFEscECFResposta.CHK). É preciso analisar todo código em cada lugar que isso acontece para ter certeza quando você está se referindo a propriedade e quando é a variável. Imagine se você confunde uma com a outra. Uma hora você pensa que sua variável está recebendo valores estranhos. Outra hora você pensa que sua propriedade não está sendo atualizada. Nesse caso específico, a variável foi renomeada para vCHK evitando a confusão com a propriedade CHK. O importante é que quando você for ler o código, não precise ficar pensando “Isso aqui é uma variável ou uma propriedade?”. Veja outro exemplo, agora no ACBrSMS: [FixInsight Warning] ACBrSMSClass.pas(192): W511 Object 'ListaSMS' created in TRY block begin try Self.Clear; if not FileExists(APath) then raise EACBrSMSException.CreateFmt('Arquivo "%s" não encontrado.', [APath]); ListaSMS := TStringList.Create; ListaSMS.LoadFromFile(APath); if ListaSMS.Count = 0 then Exit; //(bla bla bla...) finally FreeAndNil(ListaSMS); end; Não é apropriado esse código. O correto é mover a criação do objeto para fora do try..finally. Pense bem, se o objeto não for construído, você não quer que ele seja destruído. A mensagem ajudou a perceber também que esse bloco poderia ser escrito de outra maneira. Aquele raise não precisava estar dentro do try..finally. Evitando problemas futuros Rodando no pacote ACBrOpenSSL tivemos a seguinte mensagem no componente ACBrEAD: [FixInsight Optimization] ACBrEAD.pas(268): O804 Method parameter 'AChavePublicaOpenSSL' is declared but never used Quer dizer, parâmetro ‘AchavePublicaOpenSSL’ declarado mas não utilizado. Veja abaixo a a parte importante da função: function TACBrEAD.ConverteChavePublicaParaOpenSSH( const AChavePublicaOpenSSL: String): String; Var Buffer, Modulo, Expoente: AnsiString; {...} begin // https://www.netmeister.org/blog/ssh2pkcs8.html CalcularModuloeExpoente(Modulo, Expoente); Buffer := EncodeBufferSSH('ssh-rsa') + EncodeHexaSSH(Expoente) + EncodeHexaSSH('00'+Modulo); Result := 'ssh-rsa '+ EncodeBase64(Buffer); end; É estranho esse método ConverteChavePublicaParaOpenSSH não utilizar o parâmetro da chavePública. Qualquer pessoa que visse o método e tentasse chamar passando a chave pública não teria o resultado desejado. Analisando o código melhor vemos que o componente lê a chave pública por meio do método “LerChavePublica”. Nesse caso o correto seria remover o parâmetro para que não haja nenhuma confusão. E essa mensagem no TACBrBALToledo2090: [FixInsight Warning] ACBrBALToledo2090.pas(107): W508 Variable is assigned twice successively if (Length(wStrListDados[1]) = 16) then wDecimais := 1000; {APENAS BLOCO PROCESSADO} wResposta := wStrListDados[1]; //<---- sobreposto pela linha seguinte wResposta := Copy(wStrListDados[1], 5, 7); if (Length(wResposta) <= 0) then Exit; Veja que os dados de uma linha é sobreposta pela outra. O compilador nunca daria um aviso sobre isso. Mais dois exemplos de mensagens e o código a seguir: [FixInsight Warning] ACBrEscEpsonP2.pas(97): W514 Loop iterator could be out of range (missing -1?) [FixInsight Warning] ACBrEscEpsonP2.pas(100): W514 Loop iterator could be out of range (missing -1?) For I := 0 to Length(cTAGS_BARRAS) do TagsNaoSuportadas.Add( cTAGS_BARRAS[I] ); For I := 0 to Length(cTAGS_ALINHAMENTO) do TagsNaoSuportadas.Add( cTAGS_ALINHAMENTO[I] ); Essa eu não sei como não foi detectada antes. Por algum motivo não está sendo emitida a mensagem estouro quando o valor de I chega a 16 no primeiro caso e 3 no segundo. Encontrando erros gerados por Ctrl+C..Ctrl+V No pacote ACBrPAF veja a mensagem gerada: [FixInsight Optimization] ACBrPAF_T_Class.pas(137): O804 Method parameter 'ACampo2' is declared but never used function OrdenarT2(const ACampo1, ACampo2: Pointer): Integer; var Campo1, Campo2: String; begin Campo1 := FormatDateTime('YYYYMMDD', TRegistroT2(ACampo1).DT_MOV) + TRegistroT2(ACampo1).TP_DOCTO + TRegistroT2(ACampo1).SERIE + TRegistroT2(ACampo1).NUM_ECF; Campo2 := FormatDateTime('YYYYMMDD', TRegistroT2(ACampo1).DT_MOV) + TRegistroT2(ACampo1).TP_DOCTO + TRegistroT2(ACampo1).SERIE + TRegistroT2(ACampo1).NUM_ECF; Result := AnsiCompareText(Campo1, Campo2); end; Essa função é utilizada para ordenar os registros T2 do PAF. Mas veja que ela compara o registro “ACampo1” com ele mesmo. Suspeita: Ctrl+C e Ctrl+V... Quem nunca??... Outra situação diferente, mas relacionada com ordenação apareceu no ACBrSintegra. Na verdade 4 situações no ACBrSintegra, semelhantes entre si. Vou mostrar apenas uma, mas dessa vez a mensagem do FixInsight fica pra depois. Vamos a um jogo dos sete erros entre os ifs e else no código abaixo: function Sort60A(Item1, Item2: Pointer): Integer; var witem1, witem2 : TRegistro60A; begin witem1 := TRegistro60A(Item1); witem2 := TRegistro60A(Item2); if witem1.Emissao>witem2.Emissao then begin if witem1.NumSerie>witem2.NumSerie then Result:=1 else if witem1.NumSerie=witem2.NumSerie then Result:=0 else Result:=-1; end else if witem1.Emissao = witem2.Emissao then begin if witem1.NumSerie>witem2.NumSerie then Result:=1 else if witem1.NumSerie=witem2.NumSerie then Result:=0 else Result:=-1; end else begin if witem1.NumSerie>witem2.NumSerie then Result:=1 else if witem1.NumSerie=witem2.NumSerie then Result:=0 else Result:=-1; end; end; Conseguiu encontrar os erros? Bem, se você procurou diferenças, não deve ter encontrado nada. E não existe mesmo. Veja a mensagem da ferramenta: [FixInsight Warning] ACBrSintegra.pas(3410): W507 THEN statement is equal to ELSE statement São dois if e um else pra fazer a mesma coisa... A correção foi remover o IFs e ELSE.  Agora vamos ao pacote ACBrSPED. Depois de remover muitos e muitos parâmetros desnecessários apontados pelo FixInsight, veja esse código: function CodAjToStr(const AValue: TACBrCodAj): string; begin if AValue = codAjAcaoJudicial then Result := '01' else if AValue = codAjAcaoJudicial then Result := '02' else if AValue = codAjLegTributaria then Result := '03' else if AValue = codAjEspRTI then Result := '04' else if AValue = codAjOutrasSituacaoes then Result := '05' else if AValue = codAjEstorno then Result := '06'; end; A mensagem é a seguinte: [FixInsight Warning] ACBrEPCBlocos.pas(2071): W512 Odd ELSE-IF condition (review lines 2071 and 2073) Viu lá? Os dois primeiros ifs estão comparando AValue com o mesmo valor, "codAjAcaoJudicial". O segundo deveria ser "codAjProAdministrativo". Provavelmente mais um Ctrl+C..Ctrl+V. Mensagens para otimização de código Nem todas as mensagens geradas são de erros. Algumas são mensagens de otimização. Muitos dos commits que temos feito estão relacionados a uma mensagem como estas abaixo: [FixInsight Optimization] ACBrSATClass.pas(776): O801 CONST missing for unmodified string parameter 'CNPJvalue' [FixInsight Optimization] ACBrSATClass.pas(776): O801 CONST missing for unmodified string parameter 'assinaturaCNPJs' Ela pode ser gerada numa função como essa: function TACBrSATClass.AssociarAssinatura( CNPJvalue, assinaturaCNPJs : AnsiString) : String ; begin ...// um código que não altera nenhum dos parâmetros citados end; Essas mensagens estão dizendo que os parâmetros 'CNPJvalue' e ‘assinaturaCNPJs’ do tipo string não estão sendo alterados dentro da função a que eles pertencem. Nesse caso é bem provável que os parâmetros devessem ter um prefixo CONST na sua declaração, como abaixo: function TACBrSATClass.AssociarAssinatura(const CNPJvalue, assinaturaCNPJs : AnsiString) : String ; begin ...// um código que não altera nenhum dos parâmetros citados end; Não vou entrar em muitos detalhes sobre isso, mas usar CONST tem alguns benefícios, principalmente em caso de strings: A execução é mais rápida, porque o compilador pode otimizar o código. No caso de strings, não tem contagem de referências; O compilador garante que você não vai alterar os parâmetros passados gerando um efeito colateral indesejado em quem chamou as funções; O código fica mais legível, porque você pode ler que a intenção é não alterar o parâmetro passado; Como os parâmetros são imutáveis, pode tornar o código mais ThreadSafe; Se quer saber um pouco mais sobre isso, recomendo os seguintes links: All hail the “const” parameters! Is the use of ‘const’ dogmatic or rational? Concluindo... Bom pessoal, ainda temos bastante pra fazer. Contudo, queremos dizer que o FixInsight tem nos ajudado melhorar nosso código. Ficamos tão satisfeitos que entramos em contato com a TMS e eles generosamente nos cederam uma licença da versão Pro pra continuar nosso trabalho. Muito obrigado TMS. Agora, se você quer nossa opinião, essa é uma ferramenta altamente recomendada e está disponível pra toda versão do Delphi a partir do Delphi 2006. Se você tem alguma dúvida, baixe a versão trial e comece agora mesmo a usar no seu código. A versão trial limita as mensagens a 5 por units e funciona por 30 dias. Mas é o suficiente pra se perceber como é muito útil, como aconteceu com a gente. Quer um passo a passo em como utilizá-la? Veja o próximo post logo abaixo.
    3 pontos
  4. Atualização da homologação - Rev. 1: O ACBr é um projeto vivo que recebe atualizações diárias. Essas atualizações, normalmente, envolvem correções e novas funcionalidades. Para acompanhar esta realidade, adição de novos testes e revisão dos existentes são frequentes em novas homologações. Fica evidente também, que homologações antigas necessitam de revisões. Por conta disso, adicionamos nesta postagem, informações adicionais e novos testes comumente encontrado em homologações recentes. Quando houver novas funcionalidades nos componentes ocasionando a necessidade de novos testes, serão feitas novas postagem, no mesmo tópico, informando novos testes realizados com o acréscimo da revisão. Ex.: Rev. 2, Rev. 3 … Rev X. Ambiente: Computador Desktop Sistema Operacional Windows 10 64Bit atualizado (31/01/2019) Processador Intel Core 2 Duo E5400 2.20GHz Memória 2 GB USB 2.0 Testes usando os componentes e Demos do ACBr Utilizamos a versão 3.1.2 do PosPrinterTeste.exe, demo do ACBrPosPrinter, parte do projeto ACBr, para efetuar testes na impressora. A ultima versão do PosPrinterTestes.exe está disponível neste link: Durante os testes deixamos as configurações desta forma: Modelo: ppEscPosEpson; Porta: RAW:ELGIN RM22(USB); Colunas: 32; Espaços: 10; Linhas Pular: 2; Pag. codigo: pc860; KC1: 1; KC2: 0; FatorX: 1; FatorY: 1; Demais configurações não alteramos; Resultados: Logotipo: *Nota: Oficialmente, essa impressora não suporta armazenamento e impressão de logotipos. Contudo, ela suportou, com algumas limitações, os comandos enviados pelo componente ACBrPosPrinter. As limitações que encontramos são: - FatorX não pode ter valor 2. A impressora consegue imprimir, mas a imagem fica cortada. - O logotipo não imprime centralizado ou alinhado à direita. Apenas alinhado à esquerda é suportado. Page Mode: Funcionou, com pequenas limitações, de forma satisfatória. Contudo foi preciso adaptá-la ao tamanho do papel usado: Observações importantes: 1- Onde está escrito 4 posições, demonstra os espaço que sobrou para adicionar algum texto; 2- A propriedade Condensada(<c>) não funcionou para PageModes orientados Topo/Baixo (<mp_direcao>1</mp_direcao>) e Direita/Esquerda (<mp_direcao>2</mp_direcao>); Suporte a impressão de imagens e gravação de logotipos: Realizamos os testes de impressão de imagens e gravação de logotipo na impressora, através de comandos Esc/Pos. Maiores detalhes destas funcionalidades podem ser conferidos neste tópico: ok Impressão de imagem; ok Gravar logotipo na memória da impressora; ok Apagar logotipo na memória da impressora; ok Imprimir logotipo gravado na memória da impressora; Teste de acentuação: Atualizamos o teste de acentuação para demonstrar o suporte da impressora com fontes do Tipo B. Esta funcionalidade está presente na ultima versão do PosPrinterTeste.exe: Resultados: pc473: Alguns acentos circunflexos, crases e todos os til foram ignorados; pc850: Todos os acentos foram impressos corretamente; pc852: Alguns acentos circunflexos, todas as crases e os til foram ignorados; pc860: Todos os acentos foram impressos corretamente; pc1252: - Tipo A: Todos os acentos foram impressos corretamente; - Tipo B: Os caracteres com acentuação não foram interpretados corretamente pela impressora; Impressão de extrato do SAT com QRCode e Logotipo lateral: A impressora suportou os comandos enviados. Contudo, não imprimiu corretamente o cupom. Acreditamos que, o problema esteja na relação entre o tamanho do QRCode e a largura do papel, utilizada pela impressora. Os testes foram realizados com o uso do SATTeste na versão 2.1. Ele é um demo do ACBrSAT, parte do projeto ACBr. Ele está disponível neste link: https://www.projetoacbr.com.br/forum/files/file/316-sattesteexe/ Impressão de um extrato do SAT, com logotipo, usando o SATTeste: Graças a nova funcionalidade, do ACBrPosPrinter, de gravar logotipos na memória da impressora, através de comandos Esc/POS, realizamos a impressão de um extrato de SAT com o tal logotipo:
    3 pontos
  5. Para o CTe-OS você deve usar ACBrCTe.WebServices.EnviaOS. Ou ACBrCTe.Enviar que já executa os métodos de assinatura, validação, envio de acordo com o modelo e impressão do DACTE.
    3 pontos
  6. Bom dia, Ao fazer a segunda carta de correção para a mesma nota, você esta atribuindo novamente o valor UM ao campo nSeqEvento? Provavelmente sim, se tratando de carta de correção como o nome do campo diz, devemos informar o numero sequencial do evento. Para a primeira carta de correção da nota 1500 (por exemplo) o campo nSeqEvento recebe o valor 1. Para a segunda carta de correção para a mesma nota, o campo nSeqEvento recebe o valor 2. E assim por diante. Para a primeira carta de correção da nota 1550 (por exemplo) o campo nSeqEvento recebe o valor 1. Espero ter ajudado.
    3 pontos
  7. Boa tarde Suas sugestões foram disponibilizadas nos fontes do Projeto ACBr. Obrigado pela contribuição!
    2 pontos
  8. Boa tarde Waldir, Ajustes disponíveis no SVN, juntamente com outras correções deste banco. Favor atualizar os fontes... Obrigado!
    2 pontos
  9. conf manual qVol Quantidade de volumes transportados tem ocorrência 0-1 e tamanho de 1-15. A regra terá que ser a mesma para homologação e produção. Lembrando que qVol é uma informação requerida pelas transportadoras para emissão de CT-e e MDF-e.
    2 pontos
  10. Obrigado por reportar. Fechando. Para novas dúvidas, criar um novo tópico.
    2 pontos
  11. @Italo Jurisato Junior Enviei um e-mail para a prefeitura para verificar as questões do campos faltantes, provisoriamente estou informando manualmente no componente antes da impressão. Agradeço.
    2 pontos
  12. Boa tarde Italo, Após atualização dos fontes as notas puderam ser canceladas com sucesso.
    2 pontos
  13. Obrigado Felipe, vou seguir este tópico.
    2 pontos
  14. Boa tarde Henrique, Favor atualizar os fontes e refaça os testes. Me parece que configurando com o libCapicom o cancelamento funciona, já com o libWinCrypt não. O motivo é que com o libWinCrypt a assinatura e inserida no lugar errado.
    2 pontos
  15. Boa tarde, Conforme manual este campo é do tipo AlfaNumerico, por isso começa a contar posições a partir da esquerda: copy(Linha, 38, 11) Como está vindo sendo o arquivo de retorno? Se possível anexe aqui.
    2 pontos
  16. 2 pontos
  17. Ainda não tenho esse equipamento... nosso desenvolvimento se baseou no emulador A Gertec se prontificou de me enviar um...
    2 pontos
  18. O ACBr é Open Source... Já tentou debugar essa rotina ?
    2 pontos
  19. Boa noite, problemas resolvidos, obrigado.
    2 pontos
  20. O que é o ACBrPosPrinter e Esc/Pos ? Para quem ainda não conhece, o ACBrPosPrinter é o nosso componente para acesso a Impressoras de Bobinas, Não fiscais... Essas impressoras, denominadas Impressoras POS (Point of Sale), contemplam uma linguagem de impressão de linha, interna, onde podemos realizar tarefas como: Modificar os atributos de impressão Imprimir códigos de barras 1D e 2D (QRCode) Acionar dispositivos ligados a Impressora, como Gaveta de Dinheiro, Guilhotina Ler status da Impressora (Tampa aberta, pouco ou sem papel, etc) No mercado brasileiro, há vários modelos, que contemplam várias linguagens, como por exemplo: EscPos, EscBema, EscDaruma, etc... As linguagens são chamadas de "Esc", pois os comandos geralmente iniciam com o caractere não imprimível, ESC ou #27... Exemplo: se enviarmos para a Impressora a String: chr(27) + 'E' + chr(01), ligaremos o modo Negrito A grande maioria dos fabricantes, procurou seguir o padrão Epson, que é a marca mundialmente líder nesse segmento, e a sua linguagem Epson Esc/Pos... O componente ACBrPosPrinter suporta a grande maioria das linguagens e modelos existentes no mercado brasileiro... mas nem todos os recursos, estão disponíveis em todas as linguagens... Usar o ACBrPosPrinter é extremamente simples, e não requer o conhecimento de Esc/Pos... Através de suas Tags, você pode construir ricos relatórios, com várias formatações de fontes, alinhamento, Imagens, códigos de barra e QRCode... A título de Exemplo, usamos o próprio componente ACBrPosPrinter, para criar o Extrato do SAT, Unit ACBrSATExtratoESCPOS.pas e o DANFCe, unit ACBrNFeDANFeESCPOS.pas Se você usa o ACBrMonitorPLUS, poderá acessar o ACBrPosPrinter pelo objeto ESCPOS... Veja no manual: https://acbr.sourceforge.io/ACBrMonitor/ESCPOSImprimirTags.html Você pode baixar um Demo compilado do ACBrPosPrinter em: Você pode baixar uma Apresentação sobre o ACBrPosPrinter em: Se você não programa em ObjectPascal (Delphi/Lazarus), pode baixar a biblioteca (DLL) ACBrLibPosPrinter em: https://www.projetoacbr.com.br/forum/files/category/35-acbrlibposprinter/ Sobre a Impressão de Imagens no ACBrPosPrinter A muito tempo eu sentia falta dos seguintes recursos, no componente ACBrPosPrinter Impressão de Imagens Gravação e manipulação de Logos na memória da Impressora... Agora isso já é possível... Após muita pesquisa, e com a ajuda de vários outros artigos que encontrei na Internet (veja referência nos fontes), consegui implementar a Impressão de Imagens no modo "Raster Image"... Devido a característica desses equipamentos, apenas a impressão de Imagens monocromáticas é suportada. Existem vários sites de conversão de Imagem, para BMP Monocromático, on-line, como por exemplo: https://online-converting.com/image/convert2bmp/ Novos métodos no componente ACBrPosPrinter procedure ImprimirImagemStream(ABMPStream: TStream); // Permite Imprimir uma Imagem, no formato BMP Monocromático, de um Stream procedure ImprimirImagemArquivo(ArquivoBMP: String); // Carrega e imprime uma Imagem de um Arquivo. Em aplicações visuais (não console) será usado o Objeto TPicture, que permite carregar vários formatos de Imagem, podendo ser Colorida ou em Escala de cinza. A Imagem será convertida para BMP Monocromática. Entretanto, procure sempre usar Imagens BMP Moncromáticas, para evitar processamento desnecessário procedure ImprimirImagemRasterStr(const ARasterStr: AnsiString; AWidth, AHeight: Integer); // Imprime uma Imagem a partir de uma String no formato "Raster Image" (veja abaixo) procedure ImprimirLogo(AKC1: Integer = -1; AKC2: Integer = -1; AFatorX: Integer = -1; AFatorY: Integer = -1); // Imprime um Logo préviamente gravado na memória da Impressora. Se os parâmetros não foram informados, serão usados os valores de ACBrPosPrinter.ConfigLogo procedure GravarLogoStream(ABMPStream: TStream; AKC1: Integer = -1; AKC2: Integer = -1); // Grava uma Imagem de Logo, no formato BMP Monocromático, a partir de um Stream, nas posições informadas. Se os parâmetros não foram informados, serão usados os valores de ACBrPosPrinter.ConfigLogo procedure GravarLogoArquivo(ArquivoBMP: String; AKC1: Integer = -1; AKC2: Integer = -1); // Grava uma Imagem de Logo, a partir de um arquivo em Disco, nas posições informadas. Se os parâmetros não foram informados, serão usados os valores de ACBrPosPrinter.ConfigLogo procedure ApagarLogo(AKC1: Integer = -1; AKC2: Integer = -1); // Remove um Logo da memória da Impressora. Se os parâmetros não foram informados, serão usados os valores de ACBrPosPrinter.ConfigLogo Nova Tag de Bloco <bmp> - Imprime Imagem BMP monocromática. Conteúdo pode ser: Path da Imagem, Stream em Base64 ou AscII Art (0 e 1) Veja alguns exemplos de uso: Inicializa </zera>, define o alinhamento no centro </ce>, e efetua a impressão da Imagem em disco, no Path "C:\temp\acbrmono.bmp" </zera></ce><bmp>C:\temp\acbrmono.bmp</bmp> Imprimir uma Imagem de BMP Mono, codificada em Base64 <bmp> Qk3eDQAAAAAAAD4AAAAoAAAA+gAAAG0AAAABAAEAAAAAAKANAAAAAAAAAAAAAAIAAAAAAAAAAAAAAP///wD/////////////////////////////////////////wP/////////////////////////////////////////A/////////////////////////////////////////8D/////////////////////////////////////////wP4AAAAAAAAAAAAAAA8A8AAAAAAAAAAAAAAAAAAAAD/A/AAAAAAAAAAAAAAADwD4AAAAAAAAAAAAAAAAAAAAD8D4AAAAAAAAAAAAAAAPAHwAAAAAAAAAAAAAAAAAAAAHwOAAAAAAAAAAAAAAAA8APgAAAAAAAAAgAAAAAAAAAAHAwAAAAAAAAAAAAAAADwAfAAAAAAAAAcAAAAAAAAAAAcDAAAAAAAAAAAAAAAAPAA+AAAAAAAAfgAAAAAAAAAAAwIAAAAAAAAAAAAADgAQAB8AAAAAAAH+AAAAAAAAAAABAgAAAAAAAAAAAAACAAAABAAAAAAAAAAAAAAAAAAAAAEAAAAAADDvjnnNn489ngHw4zM+cPM/MD8w7PO4AAAAAAAAAAAAMN+e/c2fn7+/A/nzMz9x+z8wP7Hd27gAAAAAAAAAAAA/2ZnNzZ2YO7ODGxszf3ODOzAxsdx7uAAAAAAAAAAAABmZmc3Nj7gfs4cDGzN/c4MfMDO4ffu4AAAAAAAAAAAAH5mYzd2BmYOzBwObuzNzmxMwPzgdg7gAAAAAAAAAAAAfGb55+5+fHx4HAfP/Pn3zHzAzvvz7uAAAAAAAAAAAAA8AGAAAAAAAAAO4AAAAAAAAMDOAAAA4AAAAAAIAAAAADwAIAAAAAB4AA/AAAMAAAwAwPwAAA7gAAAABAgAAAAAAAAAAAAAAADwA4A+H/4AADwAAAAAAAAAAAAEDAAAAAAAAAAAAAAAAPAAAB//4AAAfAAAAAAAAAAAAAwOAAAAAAAAAAAAAAAA8AAAD/8AAAB4AAAAAAAAAAAAHA8AAAAAAAAAAAAAAADwAAAH/AAAAHAAAAAAAAAAAAA8D4AAAAAAAAAAAAAAAPAAAAPAAAAA4AAAAAAAAAAAAHwP4AAAAAAAAAAAAAAA8AAAAAAAAAHgAAAAAAAAAAAB/A/////////////////////////////////////////8D/////////////////////////////////////////wP/////////////////////////////////////////A/////////////////////////////////////////8D///////gAP///Af////gA//////+Af//4B///////wP///+AAeAB4AB4D+AAB/ADwAAAAf+B4AHgH///////A////4AA4AHgAHgfgAAB+APAAAAAH8HgAeAf//////8D////wADgAeAAeD4AAAB8A8AAAAAHweAB4B///////wP////AAPABwABw+AAAAB4DwAAAAAHx4AHgH///////A////+AA///AAPD4AAAAHwPAAAAAAPHgAeAf//////8D////4AB//8AA4eAAAAAHg8AAAAAAeeAB4B///////wP////wAH//wAHj4AAAAAeDwAAAAAB54AHgH///////A/////AAf/+AAePAAAAAA8PAAAAAADngAeAf//////8D////8AAAAAADx4AAAAAD48AAAAAAPeAB4D///////wP////wAAAAAAPHAAAAAAHjwAAAAAA94AHgP///////A/////gAAAAAA48AAP8AAOPAAP/gAB3gAeA///////8D////+AAAAAADjwAB/4AA48AA//AAH+AB4D///////wP////8AAAAAAe+AAP/wADzwAD/+AAf4AHgf///////A/////wAAAAAB/4AB8PgAPPAAOf4AB/gAeB///////8D/////AAAAAAP/AAHgfAAc8AA7zgAH+AB4H///////wP////+AAAAAA/8AA8A8AP7wAD/+AAd4AHg////////A/////4AAAAAD5wADgBwH/vAAP/4AD3gAeD///////8D/////wAH/AAePAAOAHB/+8AA//AAPeAA4P///////wP/////AAf8ABw8AA4Af/8DwAD/gAA54ADg////////A/////8AB/gAPDwAHgB//APAAAAAAHngAPH///////8D/////4AH+AA8PAAeAD+AA8AAAAAA+eAAf////////wP/////gAf4ADw8AB4APgADwAAAAAHx4AB/////////A/////+AA/gAf7wAHgAwAAPAAAAAA+HgAH////////8D/////8AD8AB//AAeAAAAA8AAAAAfweAAHP///////wP/////wAHwAH/8AB4AAAADwAAAAB+B4AAAf///////A//////gAfAA8fwAHgA4AAPAAAAAB8HgAAA///////8D/////+AB4ADwPAAOAH+AA8AAAAADweAAAD///////wP/////4ADgAeA8AA4Af/gDwAAAAAHh4AAAP///////A//////wAMAB4BwADgB//+PAAP/AAPHgAgAf//////8D//////AAwAHAHAAPAHP/+8AA/+AA8eACAB///////wP/////+ADAA8AcAAfx8A/7wAD/4ADx4AMAD///////A//////4AEADgB4AB//gAPPAAODgAHHgA4AP//////8D//////gAQAOAHgAD/+AA88AA8+AAeeADwB///////wP//////AAAB4AOAAH/gADjwAD/4AB5////////////A//////8AAAHgA8AAP8AAOPAAP/gAHn///////////8D//////wAAA8ABwAAAAAB48AA/wAAef///////////wP//////gAADwAHgAAAAAPDwAAAAABwAAH/////////A//////+AAAOAAOAAAAAA8PAAAAAAPAAAf////////8D//////8AAB4AA+AAAAAHg8AAAAAA8AAD/////////wP//////wAAHgAB4AAAAA8DwAAAAADgAAf/////////A///////AAA8AAD4AAAAHwPAAAAAA/AAD/////////8D//////8AADwAAPgAAAA+A8AAAAAD+AAP/////////wP//////4AAPAAAfgAAAHwDwAAAAAf4AB//////////A///////gAA4AAAfgAAB+APAAAAAHzwAP/////////8D///////AAHgAAA/gAAfwA8AAAAD/PgA//////////wP/////////8AAAB////8AD//////wfAH//////////A//////////wAAAB////gAP//////88A//////////8D//////////gAAAB///4AB////////4H//////////wP//////////AAAAAP/wAAHgAAAAB//w///////////A//////////+AAAAAAHAAA8AAAAAAf/n//////////8D//////////8AAAAAAcAAHwAAAAAAB////////////wP//////////4AAAAABwAAeAAAAAAAAf///////////A///////////wAAAAAHAADwAAAAAAAA///////////8D///////////gAAAAAcAAeAAAAAAAAH///////////wP///////////AAAAABwAD4AAAAAAAA////////////A////////////AAAAAHAAeAAAAAAAAH///////////8D///////////8AAAAAeAD4AAAAAAAA////////////wP///////////4AAAAB4APAAAAAAAAH////////////A////////////4AAAAHgB4AAAAAAAB////////////8D////////////wAAAAeAPAAAAAAAAP////////////wP////////////wAAAB4B8AAAAAAAD/////////////A/////////////gAAAHgHgAAAAAAAf////////////8D/////////////AAAAOA8AAAAAAAD/////////////wP/////////////AAAA4HwAAAAAAA//////////////A//////////////AAADgeAAAAAAAP/////////////8D//////////////AAAPHwAAAAAAD//////////////wP//////////////AAA8eAAAAAAA///////////////A///////////////AADz4AAAAAAH//////////////8D///////////////AAPeAAAAAAD///////////////wP///////////////gA/4AAAAAA////////////////A////////////////wD/AAAAAA////////////////8D////////////////wH4AAAAAP////////////////wP////////////////4fAAAAAH/////////////////A//////////////////8AAAAP/////////////////8D//////////////////8AAA///////////////////wP/////////////////////////////////////////A/////////////////////////////////////////8D/////////////////////////////////////////wA== </bmp> Imprimir uma Imagem, baseado em ASCII ART Na Unit ACBrImage.pas, do pacote ACBrComum, é onde a mágica acontece... essa Unit implementa os seguintes métodos function IsPCX(S: TStream; CheckIsMono: Boolean = True): Boolean; // Retorna True se o Stream contém uma Imagem em PCX function IsBMP(S: TStream; CheckIsMono: Boolean = True): Boolean; // Retorna True se o Stream contém uma Imagem em BMP procedure RasterStrToAscII(const ARasterStr: AnsiString; AWidth: Integer; InvertImg: Boolean; AscIIArtLines: TStrings); // Converte uma String codificada em "Raster Image", para ASCII ART procedure AscIIToRasterStr(AscIIArtLines: TStrings; out AWidth: Integer; out AHeight: Integer; out ARasterStr: AnsiString); // Converte uma String codificada em ASCII ART para "Raster Image" procedure BMPMonoToRasterStr(ABMPStream: TStream; InvertImg: Boolean; out AWidth: Integer; out AHeight: Integer; out ARasterStr: AnsiString); // Converte uma Imagem no formato BMP Monocromático, gravada em um Stream, para uma String codificada em "Raster Image" procedure RasterStrToBMPMono(ARasterStr: AnsiString; AWidth: Integer; InvertImg: Boolean; ABMPStream: TStream); // Converte uma String codificada e "Raster Image", para uma Imagem no formato BMP Monocromático, gravando-a em um Stream {$IfNDef NOGUI} procedure BitmapToRasterStr(ABmpSrc: TBitmap; InvertImg: Boolean; out AWidth: Integer; out AHeight: Integer; out ARasterStr: AnsiString; LuminosityThreshold: Byte = C_LUMINOSITY_THRESHOLD); // Apenas disponível se a aplicação não for console. converte uma Imagem de um TBitMap, para uma String codificada e "Raster Image" {$EndIf} Use a força, leia os fontes Não deixe de estudar os fontes do Projeto Demo, PosPrinterTeste, na pasta: \ACBr\Exemplos\ACBrSerial\ACBrPosPrinter\Delphi Nesse projeto há vários exemplos de como Imprimir Imagens, e manipular Logotipos, usando as Tags e Métodos do componente ACBrPosPrinter O que é o modo "Raster Image" ? O Modo Raster é um fluxo de Bytes que representam os Pixels da Imagem... https://pt.wikipedia.org/wiki/Raster Exemplo: Imagine a Seguinte imagem, de 16 x 16 Pixels... Se fôssemos representá-la em ASCII ART, teríamos: 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 1010101010101010 Para transformá-la em Raster, agrupamos os Bits, em Bytes (8 bits)... portanto a primeira linha ficaria: Em Binário: 10101010 + 10101010 Em Hexa: AA + AA Em Decimal: 170 + 170 Então a String em Raster Image, da Imagem acima seria o equivalente a: #170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170+#170 Para imprimir uma String em Raster, é fundamental sabermos qual a largura em Pixels, da imagem A Epson disponibiliza utilitário, para converter imagens para o formato Raster: Epson BmpToRaster (o estudo do conteúdo do arquivo gerado por esse Utilitário, foi essencial na implementação dos métodos de ACBrImage)
    1 ponto
  21. Não tenho ideia se a SEFAZ valida o regime da empresa. Essa é uma boa pergunta, e é provável que precise ser tirada com um contador. Vou mencionar o que eu penso que pode ser a resposta. As situações citadas me parecem gerar um novo documento, ou pelo menos, uma alteração do documento. Como as notas devem ser informadas com enfoque no declarante, é possível que seja no enquadramento atual da empresa.
    1 ponto
  22. Boa tarde Adicionado ao SVN correção sugerida, mantendo validações anteriores para não haver quebra de compatibilidade, pois algumas Cooperativas deste banco continuam validando versão anteriores. Obrigado
    1 ponto
  23. Boa tarde Suas sugestões foram disponibilizadas nos fontes do Projeto ACBr. Obrigado pela contribuição!
    1 ponto
  24. Boa Tarde, Italo! Verifiquei no site e o evento é o dia inteiro todos dias, menos o dia 18 que é abertura, fica dificil para participar como trabalho sozinho. vou esperar mais perto para ver se consigo ir. tem que confirmar presença ate o dia 13/02.
    1 ponto
  25. Fala grande Daniel! Sempre honrado em receber seu contato. Vou gerar todos os testes agora a tarde nela e te passo todas essas informações aqui.
    1 ponto
  26. Boa tarde. O @José M. S. Junior ficou de analisar. Att.
    1 ponto
  27. Obrigado por reportar. Fechando. Para novas dúvidas, criar um novo tópico.
    1 ponto
  28. Obrigado por reportar. Fechando. Para novas dúvidas, criar um novo tópico.
    1 ponto
  29. Obrigado por reportar. Fechando. Para novas dúvidas, criar um novo tópico.
    1 ponto
  30. Bom.. em teoria esses equipamentos passam por rigorosos testes de certificação... Veja como está descrito no Manual da Especificação SAT, 2_26_4, pag 78 o que dá a entender que Zero é permitido...
    1 ponto
  31. Bom dia. Segue link de download do ACbrLib https://www.projetoacbr.com.br/forum/files/category/36-acbrlib-sac/ Atualmente estamos com o ACBrLibPosPrinter, ACBrEmail e ACBrSAT implementados. Segue também link com o manual de utilização https://acbr.sourceforge.io/ACBrLib/BemVindo.html Att.
    1 ponto
  32. Bom dia, Segue unit corrigida. Aguardo atualização no svn. ACBrEFDBloco_C_Class.pas
    1 ponto
  33. Ok, vou pedir para o pessoal avaliar essa alteração proposta;
    1 ponto
  34. Prazo para implementação das alterações para CTe/CTe-OS trazidas pela NT 2018.002 v1.001 conforme resumo a seguir: Permitir relacionar NF-e emitida por emitente pessoa física com inscrição na relação de documentos transportados; Inclusão do grupo de informações do responsável técnico pelo desenvolvimento do sistema de emissão do DF-e; Inclusão da data/hora da viagem e tipo de fretamento no CT-e OS de transporte de pessoas; Inclusão de validações para o tipo de Serviço e para preenchimento do TAF ou Registro Estadual no CT-e OS Fonte: http://www.cte.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=6NPZPVLwFnw=
    1 ponto
  35. Bom dia! Era isto mesmo, muito obrigado pela ajuda.
    1 ponto
  36. Bom conforme leu acima o código não foi incorporado por existir muitas diferenças. é necessário implementar no fonte atual e anexar novamente
    1 ponto
  37. Por favor, anexe os arquivos alterados para que possa ser analisado.
    1 ponto
  38. Maiquel, Se no XML de retorno que é o XML da NFS-e não consta essas informações, então o problema é o provedor que não esta gerando. Favor entrar em contato com o provedor.
    1 ponto
  39. Bom dia, Uma coisa é a configuração do componente, outra coisa é alimentar o componente com os dados da venda. Com certeza você tem na sua aplicação uma procedure que alimenta o componente com os dados da venda, é nessa rotina que você tem que incluir o fragmento de código que postei. Outra coisa, o ambiente de homologação da NF-e só vai estar disponível para os testes a partir do dia 25/02/2019.
    1 ponto
  40. Já consegui resolver! O problema estava em como as bibliotecas estavam sendo compiladas. Ajustando os arquivos .so para EmbeddedNativeLibrary e o .jar para EmbeddedJar tudo ocorreu como planejado. Podem fechar o tópico.
    1 ponto
  41. Bom dia Roberto, A NFS-e Nacional que você se refere é a NFS-e Padrão Nacional (o novo) ou o layout da ABRASF que muitos por ai diz ser o padrão nacional? No momento as prefeituras contratam empresas que chamamos de Provedores. Esses provedores implementam o webservice que vai recepcionar o RPS, gerar a NFS-e e por fim disponibilizar os dados para a prefeitura. Na minha lista tenho por volta de 80 provedores, sendo que 10 tem o seu próprio layout, 35 usam a versão 1 do layout da ABRASF e os outros 35 usam a versão 2 do layout da ABRASF. Se a documentação que você tem se refere a nova NFS-e Padrão Nacional que visa estabelecer um único layout para todas as cidades brasileiras bem como um único webservice, se possível for gostaria de ver essa documentação.
    1 ponto
  42. Matou a charada ! Estava com este problema e com esta dica resolveu. Gratidão ! Moacir
    1 ponto
  43. Arquivo ACBrBoleto.pas com tratamento para evitar erro de conversão; ACBrBoleto.pas
    1 ponto
  44. Esclareceu muitoooo bem @Juliana Tamizou Muito obrigado
    1 ponto
  45. Boa tarde. Você está utilizando o componente ou o ACBrMonitorPlus? Tente atualizar novamente seus fontes ou o Monitor, conforme seu caso. Att.
    1 ponto
  46. Boa tarde. Estamos trabalhando no Projeto ACBrLib, porém ainda não temos a biblioteca para o MDFe, a qual deverá ser criada também. Att.
    1 ponto
  47. Boa Tarde, Só para avisar, essa semana já vou finalizar a atualização do 2240. Assim que eu finalizar e realizar os testes, postarei os fontes aqui. Obrigado!
    1 ponto
  48. Segundo ouvi dizer do pessoal da certificadora isso será apenas mais uma opção à assinatura digital, mas ainda está fase de testes e está dando muitos problemas, tanto que só a Certisign está vendendo e sem ao menos explicar direito como funciona. Acredito que para NFC-e perderá a funcionalidade da emissão em off-line. Acho precoce se preocupar com isso agora, mesmo porque só empresas grandes com muitos pontos de acesso que optarão por isso, ou não.
    1 ponto
  49. Ou trate dentro de um Try..Except como mencionado antes.
    1 ponto
  50. Notei que muitas das impressoras recém lançadas, e que Emulam Epson Esc/Pos, não estavam funcionando com comando de gravação de logotipo... Investigando o problema, notei que elas não implementam (não são compatíveis) com o comando "GS 8L", função 67 - "Define the NV graphics data (raster format)"... e usam apenas o comando legado "FS q" Fiz um ajuste, para que o comando legado seja usado, dependendo do valor definido em Keycode1 e 2 { Verificando se informou o KeyCode compatível com o comando Novo ou Antigo. Nota: O Comando novo da Epson "GS + '8L'", não é compatível em alguns Equipamentos (não Epson), mas que usam EscPosEpson... Nesse caso, vamos usar o comando "FS + 'q'", para tal, informe: KeyCode1 := 1; KeyCode2 := 0 } Portanto use os valores KeyCode1 := 1 e KeyCode2 := 0 , se a impressora não suportar o novo comando... Os ajustes já estão no SVN, e o Demo do PosPrinterTeste, já foi atualizado na área de downloads do fórum...
    1 ponto
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.