Ir para conteúdo
  • Cadastre-se

amarildolacerda

Membros
  • Total de ítens

    186
  • Registro em

  • Última visita

Tudo que amarildolacerda postou

  1. 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;
  2. 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>
  3. Alterado o comando de impressão de cheque que não estava imprimindo a palavra "centavos" no extenso do cheque. ACBrECFEpson.pas
  4. 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
  5. - 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
  6. Olá Daniel, Sabe se temos a chave CHV_CFE (a chave eletronica) do ECF TM800/TM900 da epson (Convênio 09/09 ) ?
  7. Vou olhar qual o impacto se utilizar TACBrPosComandos
  8. 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
  9. - 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.
  10. 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")
  11. 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
  12. 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
  13. 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
  14. 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.
  15. Já olhei a pasta de exemplo... e não consegui fazer muito... Na versão trunk a NFSe esta funcionando... quando migrei para o Trunk2... parou de funcionar e não estou conseguindo achar o caminho. O layout esta muito diferente: [trunk - que funciona] <?xml version="1.0" encoding="UTF-8"?> <CompNfse xmlns:ns4="http://www.ginfes.com.br/tipos_v03.xsd"> <Nfse> <InfNfse> <Numero>2096</Numero> <CodigoVerificacao>420674376</CodigoVerificacao> <DataEmissao>2016-04-04T12:34:30</DataEmissao> <IdentificacaoRps> [trunk2 - não funciona] <?xml version="1.0" encoding="UTF-8"?> <Rps xmlns:ns4="http://www.ginfes.com.br/tipos_v03.xsd"> <ns4:InfRps Id="1119004001"> <ns4:IdentificacaoRps> <ns4:Numero>1119004</ns4:Numero> <ns4:Serie>001</ns4:Serie>
  16. Inclui implementação do método virtual... CancelaItemNaoFiscal ACBrECFVirtual.pas ACBrECFVirtualBuffer.pas
  17. Grato pela atenção de todos... Não tenho nenhuma resposta ainda... se houver novidades, aviso.
  18. Olá Daniel, Gostaria de ter mais flexibilidade para escolher o local de gravação do XML... É possível incluir um evento neste procedimento ? O evento retornaria a pasta onde será gravado o XML; function TACBrSATConfigArquivos.CalcPath(APath: String; CNPJ: String; Data: TDateTime): String; ACBrSATClass.pas
  19. A Propriedade Quantidade do Registro de Produto estava tipado como INTEGER... Alterado para DOUBLE ACBrBlocoX_Comum.pas
  20. Exemplo: Vender: 1 x 1,00 = 1,00 -> desconto 0,10 = liquido -> 0,90 (ICMS F) Fecha em dinheiro, na X: valor venda = 0,90 - Lista Tributação F = 1,00 (deveria ser 0,90)
  21. Atualizei o código e o problema continua acontecendo... - quando tem desconto no item, esta interferindo no valor da base de ICMS - quando retirei a interferência do item,ai passou a dar problema como desconto/acréscimo de total... Fiz nova alteração, para acomodar em conjunto o desconto de item e desconto de total (e acréscimos). ACBrECFVirtual.pas
  22. Nesta ultima versão que baixei (hoje), o valor do desconto dos itens - quando imprime o item ele subtrai corretamente o valor do desconto.... quando entra no fechamento do cupom, tem alguma coisa estranha... que ele volta o valor do desconto para o totalizador do dia por alíquota. Estou enviando a alteração para permitir comparação.... o local onde encontrei a redundância, comentei... não entendi o código - não sei se tem outra finalidade. ACBrECFVirtual.pas
  23. nesta linha: ItemCupom.DescAcres := RoundABNT( ADescAcres, -2); Quando ADescAcres=-1,95 retorna -1,94 Alteração provisória: function RoundABNT(AValue: Double; const Digits: SmallInt):Double; var Pow, FracValue, PowValue : Extended; RestPart: Double; IntCalc, FracCalc, LastNumber, IntValue : Int64; ehNegativo:boolean; Begin ehNegativo := AValue<0; if ehNegativo then AValue := -AValue; Pow := intpower(10, abs(Digits) ); PowValue := AValue / 10 ; IntValue := trunc(PowValue); FracValue := frac(PowValue); PowValue := FracValue * 10 * Pow ; IntCalc := trunc( PowValue ); FracCalc := TruncFix( frac( PowValue ) * 100 ); if (FracCalc > 50) then Inc( IntCalc ) else if (FracCalc = 50) then begin LastNumber := round( frac( IntCalc / 10) * 10); if odd(LastNumber) then Inc( IntCalc ) else begin PowValue := PowValue * 10; RestPart := PowValue - TruncFix(PowValue); if RestPart > 0.00001 then Inc( IntCalc ); end ; end ; Result := ((IntValue*10) + (IntCalc / Pow)); if ehNegativo then Result := - Result; end;
×
×
  • 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.

The popup will be closed in 10 segundos...