-
Total de ítens
186 -
Registro em
-
Última visita
amarildolacerda's Achievements
-
Alteração para enviar QRCode versao 2.00 function TACBrNFe.AjustarVersaoQRCode(AVersaoQRCode: TpcnVersaoQrCode; AVersaoXML: TpcnVersaoDF): TpcnVersaoQrCode; begin if (AVersaoXML <= ve310) then Result := veqr000 else // ve400 ou superior Result := TpcnVersaoQrCode(max(Integer(AVersaoQRCode), Integer(veqr200))); { TODO: codigo original esta versao 100 do qrcode } end;
-
MFE - Erro /Timeout de resposta do "envia comando"
um tópico no fórum postou amarildolacerda MFE - Módulo Fiscal Eletrônico
1. Alguma situações o Integrador devolve uma resposta de Erro por conta de formatação com Erro no pacote de requisição - não há nenhum ponto para recuperar este e erro, já que o código esta esperando um erro de resposta da operação e não de erro no pacato de requisição. // pegar erro de validação do dado no envio do pacote ao integrador - Amarildo Lacerda Erro := LerTagXML(RespostaIntegrador, 'Erro', True); if Erro <> '' then DoException(Erro); 2. Constatamos um número muito elevado de situações que o "Integrador" não devolve a resposta da operação após ter capturado a XML de requisição... Fluxo: 1) aplicação gera o XML de requisição; 2) o integrador pega o XML; .... não devolve nenhum retorno e entra em "timeout"; Para avaliar a questão estamos testando a possibilidade de reenviar o mesmo pacote com os mesmos dados. Estamos ainda para avaliar se isto poderá gerar duplicidade do mesmo dado no MFE (não tenho resposta segura ainda); Como estamos fazendo isto: - incluído um contador de insucesso ao obter a resposta; - a cada insucesso incrementa o contador; - depois de um número de insucessos, gera novamente o arquivo com os mesmos dados. <code> unit ACBrIntegrador; .... function TComandoIntegrador.EnviaComando(numeroSessao: Integer; Nome, Comando: String; TimeOutComando: Integer = 0): String; var LocTimeOut, ActualTime, TimeToRetry: TDateTime; NomeArquivoXml, RespostaIntegrador: String; ATimeout: Integer; function CriarXml(NomeArquivo, Comando: String): String; var NomeArquivoTmp, NomeArquivoXml: String; begin NomeArquivoTmp := ChangeFileExt(NomeArquivo, '.tmp'); FOwner.DoLog('Criando arquivo: ' + NomeArquivoTmp); WriteToFile(NomeArquivoTmp, Comando); if not FileExists(NomeArquivoTmp) then DoException('Erro ao criar o arquivo: ' + NomeArquivoTmp); NomeArquivoXml := ChangeFileExt(NomeArquivoTmp, '.xml'); FOwner.DoLog('Renomeando arquivo: ' + NomeArquivoTmp + ' para: ' + NomeArquivoXml); if not RenameFile(NomeArquivoTmp, NomeArquivoXml) then DoException('Erro ao renomear o arquivo: ' + NomeArquivoTmp + ' para: ' + NomeArquivoXml); Result := NomeArquivoXml; end; var Erro: string; conta: Integer; begin Result := ''; Clear; conta := 0; // NomeArquivoXml := CriarXml(FPastaInput + LowerCase(Nome) + '-' + // IntToStr(numeroSessao), Comando); NomeArquivoXml := CriarXml(FPastaInput + LowerCase(Nome) + '-' + IntToStr(numeroSessao) + '-' + FormatDateTime('HHNNSS', ActualTime), Comando); // somente para debug --- remover // seria interessante ter um evento para gravar o conteúdo enviado - WriteToFile(ChangeFileExt(NomeArquivoXml, '.env'), Comando); ActualTime := Now; TimeToRetry := IncSecond(ActualTime, 3); if (TimeOutComando > 0) then ATimeout := TimeOutComando else ATimeout := FTimeout; if (ATimeout <= 0) then ATimeout := 100; LocTimeOut := IncSecond(ActualTime, ATimeout); RespostaIntegrador := AguardaArqResposta(numeroSessao); while EstaVazio(RespostaIntegrador) and (ActualTime < LocTimeOut) do begin Sleep(150); RespostaIntegrador := AguardaArqResposta(numeroSessao); ActualTime := Now; if ActualTime > TimeToRetry then // Caso arquivo ainda não tenha sido consumido após 5 segundos, recria o arquivo begin // se tentou e não retornou nenhum dado... renenviar inc(conta); TimeToRetry := IncSecond(ActualTime, 3); if (FilesExists(NomeArquivoXml)) or (conta > 2) then begin try FOwner.DoLog('Apagando arquivo não processado: ' + NomeArquivoXml); DeleteFile(NomeArquivoXml); except end; NomeArquivoXml := CriarXml(FPastaInput + LowerCase(Nome) + '-' + IntToStr(numeroSessao) + '-' + FormatDateTime('HHNNSS', ActualTime), Comando); conta := 0; end; end; end; /// somente para debug - remover /// remove o arquivo gerado para DEBUG... houve sucesso if (not EstaVazio(RespostaIntegrador)) and FileExists(debug) then DeleteFile(debug); if FilesExists(NomeArquivoXml) then // Apaga arquivo não tratado pelo Integrador begin FOwner.DoLog('Apagando arquivo: ' + NomeArquivoXml); DeleteFile(NomeArquivoXml); end; if EstaVazio(RespostaIntegrador) then begin FErroTimeout := True; DoException('Sem Resposta do Integrador'); end; // pegar erro de validação do dado no envio do pacote ao integrador - Amarildo Lacerda Erro := LerTagXML(RespostaIntegrador, 'Erro', True); if Erro <> '' then DoException(Erro); FOwner.DoLog('RespostaIntegrador: ' + RespostaIntegrador); FResposta := RespostaIntegrador; FIntegradorResposta.LerResposta(RespostaIntegrador); Result := PegaResposta(RespostaIntegrador); end; </code> -
ECF Epson - não imprimia texto "Centavos" no cheque
um tópico no fórum postou amarildolacerda ACBrSerial
Alterado o comando de impressão de cheque que não estava imprimindo a palavra "centavos" no extenso do cheque. ACBrECFEpson.pas -
A implementação para checar se a porta é uma DLL não estava funcionando (não reconhecia DLL1). Alterado para: else if (pos(copy(UPorta,1,3),'USB|DLL') > 0) then /// Amarildo Lacerda: correção Result := dtHook ACBrDevice.pas
- 3 replies
-
- 1
-
- epson
- acbrserial
-
(e 1 mais)
Tags:
-
ECFVirtual - Impressora Toshiba 1 e 2 Estações
amarildolacerda replied to amarildolacerda's tópico in ACBrSAT
- Segue o código da ESC Toshiba que estou usando em produção. ACBrSerial_ESC_Toshiba.rar - Documentação oficial para a impressora Toshiba 4610ProgrammersGuide.rar -
Olá Daniel, Sabe se temos a chave CHV_CFE (a chave eletronica) do ECF TM800/TM900 da epson (Convênio 09/09 ) ?
-
amarildolacerda started following Guilherme HA
-
ECFVirtual - Impressora Toshiba 1 e 2 Estações
amarildolacerda replied to amarildolacerda's tópico in ACBrSAT
Sim.... implementar o PuloDeLinha RESOLVE -
ECFVirtual - Impressora Toshiba 1 e 2 Estações
amarildolacerda replied to amarildolacerda's tópico in ACBrSAT
Vou olhar qual o impacto se utilizar TACBrPosComandos -
Conclusão para portar a impressora da Toshiba PosPrinter Classe: TACBrEscToshiba. Algumas alterações que foram necessárias: 1) a impressora não pode receber #13#10 - precisa ser substuido por #13 (estava gerando um salto adicional de linha). Para completar esta imprementação foi preciso implementar um novo evento em: TACBrPosPrinter property OnTratarImprimir : TACBrTagOnTraduzirTag read FOnTratarImprimir write SetOnTratarImprimir; o evento irá receber a string para impressão e substuir o #13#10 por #13 (na classe: TACBrEscToshiba) no create será atribuido o evento para que a substituição seja feita. constructor TACBrEscToshiba.Create(AOwner: TACBrPosPrinter); begin inherited Create(AOwner); AOwner.OnTratarImprimir := DoTratarImprimir; ..... 2) Reintroduzi a TACBrEscPosChequeClass = class na TACBrPosPrinter Este código que suporte a impressão de cheque já estava integrado. Nas últimas atualizações ele foi removido. 3) implementado a impressão de cheque na Toshiba - Layout dos cheque é o mesmo fornecedo pelo fabricante. 4) anexo o PDF com os codigo EscPOS de comandos para a impressora ( esgotou espaço - vou subir em outro POST) . ACBrPosPrinter.pas ACBrEscPosChequeToshiba.pas ACBrEscToshiba.pas checkLayouts.xml
-
Impressão de Cheque - EPSON TM-H6000 III
amarildolacerda replied to giulianon's tópico in ACBrSerial
- se observar o código... toda vez que chama o cheque... ele reprograma o cheque para o indice 01.... ou seja, o indice sempre é o mesmo com novas posições de impressão. -
Eu deve ter perdido alguma coisa... Estou procurando onde pegar a Chave CFe do cupom no ECF da Epson T800F e não estou conseguindo localizar. Na DLL, a Epson indicou a função: EPSON_ESC_ECF_Obter_Chave_Busca_CFE Temos em algum lugar esta informação ? (motivo: no SPED C465 ele exige "CHV_CFE - Chave cupom fiscal eletrônico")
-
Arredondamento de Desconto de Total - Como resolver na versão 0.06
amarildolacerda replied to amarildolacerda's tópico in ACBrSAT
http://www.fazenda.sp.gov.br/sat/downloads/Especificacao_SAT_v_ER_2_19_07.pdf 1- Desconto sobre subtotal deverá ser rateado proporcionalmen te ao valor de cada item, já considerado o desconto ou acréscimo sobre item; 2- Diferença entre o valor do desconto sobre subtotal e a soma dos seus rateios deve ser Especificação Técnica de Requisitos - SAT - Direitos Reservados - Versão ER 2.19.07 de 18/05/2016 72 alocada ao rateio de maior valor -
Arredondamento de Desconto de Total - Como resolver na versão 0.06
um tópico no fórum postou amarildolacerda ACBrSAT
A versão 0.06 do SAT não tratou corretamente a questão do arredondamento do rateio de desconto de subtotal para os itens resultando em valor diferente quando do somatório dos rateios dos itens em relação ao valor de desconto no total. Na versão 0.07, isto foi resolvido da seguitne forma... depois de fazer o rateio ajusta-se a diferença no item de maior valor. Pensando nisto, fiz alterações que permitam replicar a mesma coisa para a versão 0.06 1) incluido novo evento no ACBrECFVirtualSAT - QuandoFechaCupom 2) no evento QuandoFecharCupom - implementado... procedure TConectorSATEletronico.DoQuandoFechaCupom(CFe: TCFe); var vDescTotal: double; var i, iMax: integer; vMax: double; fator: double; vDescItem: double; vDescAcum: double; vProd: double; vItem:double; function RoundECF(valor:Double):double; begin result := FServer.ECFVirtual.ECFVirtualClass.RoundECF(valor); // usa o tipo de arredondamento configurado no ECFVirtual; end; begin inherited; // na versao 0.06 o arredondamento esta com diferença de arredondamento. // tentativa de correção do arredondamento, fazendo rateio pelos itens. vDescTotal := CFe.Total.DescAcrEntr.vDescSubtot; if (vDescTotal > 0) and (FloatToString( CFe.infCFe.versaoDadosEnt) = FloatToString(0.06)) then begin iMax := 0; vDescAcum := 0; vProd := 0; for i := 0 to CFe.Det.count - 1 do begin vItem := RoundECF( CFe.Det.Items.Prod.qCom * CFe.Det.Items.Prod.vUnCom); vProd := vProd + vItem; end; if vProd > 0 then begin fator := vDescTotal / vProd; for i := 0 to CFe.Det.count - 1 do begin vItem := RoundECF( CFe.Det.Items.Prod.qCom * CFe.Det.Items.Prod.vUnCom); if vItem > vMax then begin iMax := i; vMax := vItem; // guarda o item de maior valor -- conforme determinou a norma tecnica para a versao 0.07 end; vDescItem := RoundECF(vItem * fator); CFe.Det.Items.Prod.VDesc := CFe.Det.Items.Prod.VDesc + vDescItem; vDescAcum := vDescAcum + vDescItem; end; // ajusta a diferença CFe.Det.Items[iMax].Prod.VDesc := CFe.Det.Items[iMax].Prod.VDesc + (vDescTotal - vDescAcum); CFe.Total.DescAcrEntr.vDescSubtot := 0; end; end; end; ACBrECFVirtualSAT.pas -
ECFVirtual - Alteração indice dos totalizadores
um tópico no fórum postou amarildolacerda ACBrSerial
No ACBrECFVirtual.pas -> quando inicializa os totalizadores são instânciados na sequência FF, II e NN - (base 0 -> 0, 1 , 2.... Quando chama o TotalNaoTributado -> estava pegando na posição 1... deveria ser 2 No TotalIsento -> estava pegando na posição 2... deveria ser 1 Alterado para acertar o local onde pega os totalizadores e mantido a sequência FF, II, NN ACBrECFVirtual.pas- 1 reply
-
- 1
-
Epson TM800F - Não esta abrindo porta serial no Trunk2
amarildolacerda replied to amarildolacerda's tópico in ACBrSerial
Fazendo aniversário.... o problema voltou.... Ou Seja, Não estava resolvido.... O problema ocorre quando a maquina é um windows 10... em particular com EPSON USB emulando serial.