Ir para conteúdo
  • Cadastre-se

Erro de arredondamento (mais ou menos)


Ver Solução Respondido por Daniel Braz de Oliveira,
  • Este tópico foi criado há 1598 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á 1598 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.

The popup will be closed in 10 segundos...
The popup will be closed in 10 segundos...