Ir para conteúdo
  • Cadastre-se

dev botao

Erro de arredondamento (mais ou menos)


Ver Solução Respondido por Daniel Braz de Oliveira,
  • Este tópico foi criado há 1020 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Postado

Bom dia 

Vou explicar o titulo do post.
Será um tanto extenso, mas preciso qualificar a situação em busca da solução.

Antes de mais nada, quero relatar que já tentei diversas maneiras de contornar este problema.
Desde o dia 03/01/2022, estou com esta demanda num cliente.
Resumindo:
1 - Temos um rotina de geração do borderô, que é a vinculação do titulo à um banco com a devida carteira e configurações de cada banco. Aqui não uso nada do ACBR.
2 - Depois de pronto o borderô, é gerado o arquivo remessa, onde uso os componentes do ACBR.

Agora pasmem:
Se a geração da remessa for realizada imeditamente à criação do borderô, embora na tela de conferencia dos titulos, os valores com centavos estejam corretos,
pois o sistema já faz todos os calculos de tributos, descontos e retenções antecipadamente, já gerando o contas a receber e os valores para a emissão da notafiscal de serviços com os valores finais, já arredondados, conforme regras financeiras, quando é associado o valor do título ao Titulo.ValorDocumento, os valores com centavos, são acrescidos de 0,01, gerando inconsistências, pois o boleto gerado no sistema está com o valor correto, a nota fiscal emitida com o valor correto, mas o titulo enviado para o banco, com o 0,01 acrescido.
Fiz o debug e percebi que o valor é acrescido após a execução deste procedimento do AcbrBoleto:

procedure TACBrTitulo.setValorDocumento(const AValue: Currency);
begin
  fValorDocumento := RoundABNT(AValue, 2);  

end;

Quando o foco volta para a instrução  Titulo.ValorDocumento ele recebe o valor com 4 casas decimais. Por exemplo, o valor do titulo é 10,37, ele retorna 10,3701, provocando o arredondamento para 10,38. 

Quando disse acima, 'Agora pasmem', é porque o que vou relatar a seguir é no mínimo inusitado. Se o sistema for fechado e reaberto e for gerado a remessa novamente, os valores todos saem corretamente. Inclusive o mesmo borderô que foi gerado com erro. Sem o acrescimo dos 0,01. Também ficam corretos, se outro usuário, fizer a remessa em outro computador.
Se fosse no PHP, eu dia que a 'sessão' da geração borderô ficou com sujeira na memória. 
A solução paliativa encontrada, foi conversar com o pessoal do financeiro para criar os borderôs e outra pessoa gerar a remessa, ou fechar e reabrir o sistema.
Claro que a empresa não gostou muito e me exigiu resolução imediata.

Fiz uma alteração na procedure conforme abaixo:
procedure TACBrTitulo.setValorDocumento(const AValue: Currency);
begin
  // O arredondamento é com objetivo de remover as diferenças em arredondamentos posteriores,
  //    que causa uma diferença entre o valor do documento e a linha digitável.
  fValorDocumento := AValue;  // testado por daniel - 05-02-2022 

end;

Onde não executo a função RoundABNT;
Os valores ficaram corretos mesmo gerando a remessa na mesma 'sessão' do borderô. Será que posso ter problemas? Afinal o valor enviado pelo banco de dados é exatamente o que deve ser gerado na remessa.

Enfim o problema não é a função, mas alguma coisa que influencia a função, dependendo de como foi invocada.
Há alguma coisa que eu possa pesquisar ?
Como sou um dinossauro, este sistema roda no Delphi 7, com Postgres. E claro, sempre funcionou corretamente.

Desculpe o tamanho do texto.
Quem quiser dar um pitaco, fique à vontade.
Grato.

  • Consultores
Postado

Como ao fechar e abrir novamente a RoundABNT não gera o valor errado é muito provável que o valor que ela está recebendo está vindo diferente e talvez você tenha que focar nessa origem para resolver o problema.

Obviamente, como pediu para arredondar para 2 casas não deveria retornar com 4, o que também pode ter um erro na função.

Faça um teste com este exemplo, gerando todo o processo do zero e, no local que você está preenchendo o ValorDocumento, já deixa o valor fixo no fonte sem pegar de campos ou dataset.

ValorDocumento := 10.37;

Se o problema não acontecer, fica na origem do valor.

  • Moderadores
Postado
4 horas atrás, Daniel Braz de Oliveira disse:

Quando disse acima, 'Agora pasmem', é porque o que vou relatar a seguir é no mínimo inusitado. Se o sistema for fechado e reaberto e for gerado a remessa novamente, os valores todos saem corretamente. Inclusive o mesmo borderô que foi gerado com erro. Sem o acrescimo dos 0,01. Também ficam corretos, se outro usuário, fizer a remessa em outro computador.

Você usa o SetRoundMode em algum lugar dessa rotina?

Equipe ACBr BigWings
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

 

  • Consultores
Postado

Tecnicamente falando, aí lascou... 🤔🤣

O bug na função eu tinha até previsto, mas achei que fosse provocado por um valor muito quebrado recebido para arredondamento.

Vamos à caça às bruxas.

1. Se você passar 10.3700 muda o resultado?

2. Debuga sua rotina normal, sem o valor fixo, e veja os valores passados para a função na primeira vez que gera errado e na segunda que gera certo. Algo deve estar diferente para funcionar na segunda vez.

  • Consultores
Postado

Se fvalordocumento for float pode ser esse o problema, aí mudar para Double ou currency

  • Curtir 1
Consultor SAC ACBr

Victor H Gonzales - Pandaaa
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.  Discord

Projeto ACBr - A maior comunidade Open Source de Automação Comercial do Brasil

Participe de nosso canal no Discord e fique ainda mais próximo da Comunidade !!

"Aprender é a única coisa que a mente nunca se cansa, nunca tem medo e nunca se arrepende” - Leonardo da Vinci

"Ter sucesso é falhar repetidamente, mas sem perder o entusiasmo"

  • Moderadores
Postado
21 horas atrás, Daniel Braz de Oliveira disse:

Respondendo a BigWings, não uso  SetRoundMode em nenhum lugar do sistema.

Experimenta capturar o valor de GetRoundMode antes de informar a propriedade ValorDocumento e veja qual o resultado.

uses Math;

var
  rm: TFPURoundingMode;
begin
  rm := GetRoundMode;

 

Equipe ACBr BigWings
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr

 

 

Postado

Bom dia.

Creio que estou chegando à conclusão final.

Seguindo a  sugestão do BigWings, capturei o SetRoundMode.
Quando executo no modo direto, isto é, gerando o borderô e em seguida gerar a remessa que apresente o erro,  o SetRoundMode está 

image.png.7a9d36147fce9f0f95514fe97831ea66.png

Mas quando feclho o programa e reabro, quando gera correto está:
image.png.3584e0159b30f12d5bdc7c54ff137a46.png

 

Pelo jeito, a solução deva ser setar para RmNearest, cada vez que entrar nesta rotina.
Vou testar agora e posto aqui na sequencia.

 

  • Consultores
Postado
2 minutos atrás, Daniel Braz de Oliveira disse:

Bom dia.

Creio que estou chegando à conclusão final.

Seguindo a  sugestão do BigWings, capturei o SetRoundMode.
Quando executo no modo direto, isto é, gerando o borderô e em seguida gerar a remessa que apresente o erro,  o SetRoundMode está 

image.png.7a9d36147fce9f0f95514fe97831ea66.png

Mas quando feclho o programa e reabro, quando gera correto está:
image.png.3584e0159b30f12d5bdc7c54ff137a46.png

 

Pelo jeito, a solução deva ser setar para RmNearest, cada vez que entrar nesta rotina.
Vou testar agora e posto aqui na sequencia.

 

em que momento é trocado para rmUP?

consegue debugar e achar o momento em que é trocador para rmUP e não retorna para o rmNearest?

Consultor SAC ACBr

Victor H Gonzales - Pandaaa
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.  Discord

Projeto ACBr - A maior comunidade Open Source de Automação Comercial do Brasil

Participe de nosso canal no Discord e fique ainda mais próximo da Comunidade !!

"Aprender é a única coisa que a mente nunca se cansa, nunca tem medo e nunca se arrepende” - Leonardo da Vinci

"Ter sucesso é falhar repetidamente, mas sem perder o entusiasmo"

  • Consultores
Postado
1 minuto atrás, Daniel Braz de Oliveira disse:

Victor, bom dia.

Sinceramente, não tive paciência ainda em tentar descobrir isso. 😇
Adicionou uma instrução para setar para rmNearest e à principio funcionou.

Vou fazer testes ao longo do dia.

Agradeço a todos que 

Você tem uma função chamada RountTo5 implementada no seu código geralmente no bloco de nfse?

Consultor SAC ACBr

Victor H Gonzales - Pandaaa
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.  Discord

Projeto ACBr - A maior comunidade Open Source de Automação Comercial do Brasil

Participe de nosso canal no Discord e fique ainda mais próximo da Comunidade !!

"Aprender é a única coisa que a mente nunca se cansa, nunca tem medo e nunca se arrepende” - Leonardo da Vinci

"Ter sucesso é falhar repetidamente, mas sem perder o entusiasmo"

  • Solution
Postado

Prezados. Encontrado o problema.
Realmente, a dica do Victor complementou todas as outras.
Na rotina do faturamento, que entecede o borderô e a remessa há uma instrução do SetRoundMode(rmUp);
E fui eu quem pus lá. 🤐
Me lembrei que no final do ano, a pessoa do financeiro me passou a reclamação de um cliente que queria que fosse alterado o arredondamento da nota fiscal, pois como era orgão público tinham uma política rígida.
Sinceramente, não sei porque eu inseri esta instrução.
Por ora, problema está resolvido quanto à geração da remessa na 'mesma sessão', resumindo assim.
Agora vou rever a rotina do faturamento e tentar entender porque a instrução está lá.

Agradeço a todos que cooperaram e foram me abrindo a mente. Quem está no meio do problema, geralmente olha sómente numa direção.
Se cumpriu aqui o que está no livro de Provérbios 24:6b - 'há sabedora na multidão de conselheiros'.
Valeu mesmo gente.
Abraço.
 

  • Consultores
Postado

Obrigado por reportar.

Fechando. Para novas dúvidas, criar um novo tópico.

Consultor SAC ACBr

Victor H Gonzales - Pandaaa
Ajude o Projeto ACBr crescer - Assine o SAC

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.  Discord

Projeto ACBr - A maior comunidade Open Source de Automação Comercial do Brasil

Participe de nosso canal no Discord e fique ainda mais próximo da Comunidade !!

"Aprender é a única coisa que a mente nunca se cansa, nunca tem medo e nunca se arrepende” - Leonardo da Vinci

"Ter sucesso é falhar repetidamente, mas sem perder o entusiasmo"

  • Este tópico foi criado há 1020 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.
Visitante
Este tópico está agora fechado para novas respostas
×
×
  • 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.