Problema para identificar produto com custo diferente se o valor tiver casas decimais.
Em um sistema de terceiro, existe uma condição no cadastro do produto que pode ser vinculado vários produtos por um grupo, e todos os produtos deste grupo vão ter o mesmo preço de custo e venda. Porém existe um bug que permite que exista preço de custo ou venda diferentes dentro do grupo. Então o que eu estou fazendo é tentar identificar os grupos que tem produtos com custo e venda diferentes para corrigir manualmente depois.
O que eu estou fazendo.
Fiz uma query que busca todos os grupos na tabela.
Em outra query eu trago os produtos que pertencem ao primeiro registro da query anterior.
A variável custo recebe o custo de todos os produtos do grupo. (Se tiver 5 produtos com o custo R$2,00 o valor da variável custo será R$10,00).
A variável i sempre soma + 1; então o valor dela sempre será a quantidade de produtos.
Se eu dividir o custo pela quantidade de produtos 10 / 5 o resultado será 2.
Então eu comparo a variável custo com o valor do produto na query se ele for diferente o produto tem erro... se não está certo..., porém do jeito que eu fiz ele traz como resultado 2990 grupos com erro, e no sistema existe 3361 grupos. Confiro manualmente e maioria está correta. O que eu observei foi que os produtos que tem valores inteiros ele calcula certo... os valores que tem casa decimal todos ele marca como erro.
Já usei variável double e currency, select com e sem cast, usei o formatfloat e também não tive sucesso. Alguém poderia me ajudar?
Estou usando Delphi 10.3 / PostgreSQL 9.6.9 / TFDQuery
O que eu estou fazendo.
Fiz uma query que busca todos os grupos na tabela.
Em outra query eu trago os produtos que pertencem ao primeiro registro da query anterior.
A variável custo recebe o custo de todos os produtos do grupo. (Se tiver 5 produtos com o custo R$2,00 o valor da variável custo será R$10,00).
A variável i sempre soma + 1; então o valor dela sempre será a quantidade de produtos.
Se eu dividir o custo pela quantidade de produtos 10 / 5 o resultado será 2.
Então eu comparo a variável custo com o valor do produto na query se ele for diferente o produto tem erro... se não está certo..., porém do jeito que eu fiz ele traz como resultado 2990 grupos com erro, e no sistema existe 3361 grupos. Confiro manualmente e maioria está correta. O que eu observei foi que os produtos que tem valores inteiros ele calcula certo... os valores que tem casa decimal todos ele marca como erro.
Já usei variável double e currency, select com e sem cast, usei o formatfloat e também não tive sucesso. Alguém poderia me ajudar?
Estou usando Delphi 10.3 / PostgreSQL 9.6.9 / TFDQuery
var Custo,Venda : Double; i : Integer; begin MemoCusto.Clear; MemoVenda.Clear; MemoCusto.Lines.Add('Problema no Preço Referencial'); MemoVenda.Lines.Add('Problema no Preço de Venda'); with qryGrupo do begin Close; Open('SELECT id,nome FROM gruporemarcacao'); Active:=True; First; end; while not qryGrupo.EOF do begin with qryProduto do begin Close; Open('SELECT etiqueta,CAST(precoreferencial AS DECIMAL(6,2)),CAST(precovenda AS DECIMAL(6,2)) FROM embalagem WHERE gruporemarcacaoid = ' + qryGrupo.Fields[0].Text); //Open('SELECT etiqueta,precoreferencial,precovenda FROM embalagem WHERE gruporemarcacaoid = ' + qryGrupo.Fields[0].Text); Active:=True; First; end; Custo:=0; Venda:=0; i:=0; while not qryProduto.Eof do begin i:=i+1; Custo:= Custo + StrToFloat(qryProduto.Fields[1].Text); qryProduto.Next; end; Custo:= Custo / i; if Custo <> StrToFloat(qryProduto.Fields[1].Text) then begin MemoCusto.Lines.Add(qryGrupo.Fields[1].Text); end; qryGrupo.Next; end; StatusBar1.Panels[1].Text:=IntToStr(MemoCusto.Lines.Count-1) + ' Grupos com problema de custo'; end;
Paulo
Curtidas 0
Respostas
Emerson Nascimento
15/01/2021
não precisa fazer todo esse cálculo. basta procurar por valores diferentes.
a forma abaixo já avalia as duas condições (custo e venda) com uma performance muito melhor do que fazer o cálculo da forma como estava sendo feito.
a forma abaixo já avalia as duas condições (custo e venda) com uma performance muito melhor do que fazer o cálculo da forma como estava sendo feito.
var strGrupo: string; begin MemoCusto.Clear; MemoCusto.Lines.Add('Problema no Preço Referencial'); MemoVenda.Clear; MemoVenda.Lines.Add('Problema no Preço de Venda'); with qryGrupo do begin Close; SQL.Text := 'SELECT gr.id, gr.nome, '+ ' COUNT(DISTINCT CAST(e.precoreferencial AS DECIMAL(15,2))) precoref, '+ ' COUNT(DISTINCT CAST(e.precovenda AS DECIMAL(15,2))) precoven '+ 'FROM gruporemarcacao gr '+ 'INNER JOIN embalagem e ON e.gruporemarcacaoid = gr.id '+ 'GROUP BY gr.id, gr.nome '+ 'HAVING (COUNT(DISTINCT CAST(e.precoreferencial AS DECIMAL(15,2))) > 1) '+ 'OR (COUNT(DISTINCT CAST(e.precovenda AS DECIMAL(15,2))) > 1) '; Open; // só haverá registros se algum preço estiver diferente, então não precisa condicionar while not EOF do begin strGrupo := FieldByName('nome').Text; // avalia o preco de custo if FieldByName('precoref').AsInteger > 1 then MemoCusto.Lines.Add(strGrupo); // avalia o preco de venda if FieldByName('precoven').AsInteger > 1 then MemoVenda.Lines.Add(strGrupo); Next; end; end; StatusBar1.Panels[1].Text := IntToStr(MemoCusto.Lines.Count-1) + ' grupos com problema de custo'; // StatusBar1.Panels[2].Text := IntToStr(MemoVenda.Lines.Count-1) + ' grupos com problema de venda'; end;
GOSTEI 0
Paulo
15/01/2021
Emerson realmente sua logica ficou muito melhor e mais simples... eu não tinha pensado em algo parecido, meu muito obrigado seu código funcionou perfeitamente e sua logica me deu uma visão diferente para o problema.
Obrigado, forte abraço.
Problema resolvido!
Obrigado, forte abraço.
Problema resolvido!
não precisa fazer todo esse cálculo. basta procurar por valores diferentes.
a forma abaixo já avalia as duas condições (custo e venda) com uma performance muito melhor do que fazer o cálculo da forma como estava sendo feito.
a forma abaixo já avalia as duas condições (custo e venda) com uma performance muito melhor do que fazer o cálculo da forma como estava sendo feito.
var strGrupo: string; begin MemoCusto.Clear; MemoCusto.Lines.Add('Problema no Preço Referencial'); MemoVenda.Clear; MemoVenda.Lines.Add('Problema no Preço de Venda'); with qryGrupo do begin Close; SQL.Text := 'SELECT gr.id, gr.nome, '+ ' COUNT(DISTINCT CAST(e.precoreferencial AS DECIMAL(15,2))) precoref, '+ ' COUNT(DISTINCT CAST(e.precovenda AS DECIMAL(15,2))) precoven '+ 'FROM gruporemarcacao gr '+ 'INNER JOIN embalagem e ON e.gruporemarcacaoid = gr.id '+ 'GROUP BY gr.id, gr.nome '+ 'HAVING (COUNT(DISTINCT CAST(e.precoreferencial AS DECIMAL(15,2))) > 1) '+ 'OR (COUNT(DISTINCT CAST(e.precovenda AS DECIMAL(15,2))) > 1) '; Open; // só haverá registros se algum preço estiver diferente, então não precisa condicionar while not EOF do begin strGrupo := FieldByName('nome').Text; // avalia o preco de custo if FieldByName('precoref').AsInteger > 1 then MemoCusto.Lines.Add(strGrupo); // avalia o preco de venda if FieldByName('precoven').AsInteger > 1 then MemoVenda.Lines.Add(strGrupo); Next; end; end; StatusBar1.Panels[1].Text := IntToStr(MemoCusto.Lines.Count-1) + ' grupos com problema de custo'; // StatusBar1.Panels[2].Text := IntToStr(MemoVenda.Lines.Count-1) + ' grupos com problema de venda'; end;
GOSTEI 0