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