Delphi ajuda no Update do estoque

MySQL

CRUD - Delphi

04/11/2018

Caros amigos ha dias estou tentando descobrir uma forma de dar um update na minha tabela de estoque ao cadastrar o mesmo produto.
Tenho uma tabela chamada preentraitens que recebe os itens do xml de entrada, e tenho uma tabela produtos que recebe esses itens após finalizar o cadastro.
preciso dar um update na tabela produtos ao surgir um produto que ja esteja cadastrado.
Tenho este sql abaixo
with SqlUpdatePro do
         begin
           close;
           sql.clear;
           sql.add('update produtos, preentraitens set qtdun = qtdun + qtde');
           sql.add('where codbarras = codbarpro and NumNota = :nota ');
           ParamByName('nota').Value := Ide.nNF;
           ExecSQL;
         end; 

Ele funciona mais em vez de somar a quantidade que ja tem pela nova quantidade, ele estar multiplicando pelo valor total das quantidades
Ex: se a nota de entrada tem 10 itens que já esteja cadastrado ele pega cada item e soma 10 vezes.
Alguém poderia me dar uma ajuda ?
Jean Carlos

Jean Carlos

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

04/11/2018

Mas onde você está indicando o item a ser somado e a nova quantidade???
deveria ser algo assim:
for i := 1 to Det.Itens
	with SqlUpdatePro do
	begin
		close;
		sql.clear;
		sql.add('update produtos, preentraitens set qtdun = qtdun [sinaldemais] :qtde');
		sql.add('where codbarras = :codbarpro and NumNota = :nota ');
		ParamByName('nota').Value := Ide.nNF;
		ParamByName('qtde').Value := Det.Item[i].qCom;
		ParamByName('codbarpro').Value := Det.Item[i].cEAN;
		ExecSQL;
	end;

GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Amigo Emerson
Veja minha função completa para update no estoque

 function updateproexistente() : string;
var
 n, I : integer;
 ean : string;
 qtd : Currency;
 begin
 for n:=0 to FormNotasEntrada.ACBrNFe1.NotasFiscais.Count-1 do
  begin
    with FormNotasEntrada.ACBrNFe1.NotasFiscais.Items[n].NFe do
   begin
      for I := 0 to Det.Count-1 do
     begin
      with Det.Items[I] do
    begin

       with FormLerXml do
       begin
        with SqlUpdatePro do
         begin
          close;
          sql.clear;
          sql.add('update produtos, preentraitens set qtdun = qtdun + :qtde');
          sql.add('where codbarras = :cod and NumNota = :nota ');
          ParamByName('nota').Value := Ide.nNF;
          ParamByName('qtde').Value := Det.Items[i].Prod.qCom;
          ParamByName('cod').Value := Det.Items[i].Prod.cEAN;
          ExecSQL;
         end;
      end;
     end;
    end;
   end;
  end;
 end;


Fiz algumas mudanças depois da sua dica, mais continua somando pela quantidade total de itens que vem na nota
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

04/11/2018

Veja se o problema não está na instrução SQL.

Tente atualizar somente a tabela produtos.

function updateproexistente() : string;
var
 n, I : integer;
 ean : string;
 qtd : Currency;
begin
  FormLerXml.SqlUpdatePro.close;
  FormLerXml.SqlUpdatePro.sql.clear;
  FormLerXml.SqlUpdatePro.sql.add('update produtos set qtdun = qtdun + :qtde');
  FormLerXml.SqlUpdatePro.sql.add('where codbarras = :cod');

  for n := 0 to FormNotasEntrada.ACBrNFe1.NotasFiscais.Count-1 do
    with FormNotasEntrada.ACBrNFe1.NotasFiscais.Items[n].NFe do
    begin
      for I := 0 to Det.Count-1 do
        with Det.Items[I] do
        begin
          with FormLerXml.SqlUpdatePro do
          begin
            ParamByName('nota').Value := Ide.nNF;
            ParamByName('qtde').Value := Prod.qCom;
            ParamByName('cod').Value := Prod.cEAN;
            ExecSQL;
          end;
        end;
    end;

end;
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Amigo Emerson, não sei o que estar acontecendo, fiz de acordo com suas dicas , mais continua o mesmo resultado.
Uma observação: o meu codigo estava funcionando, deixou de funcionar depois que eu deletei a tabela produtos e criei uma nova,
o codigo que eu usava e funcionava certinho é este abaixo

function updateproexistente() : string;
var
n, I : integer;
begin
for n:=0 to FormNotasEntrada.ACBrNFe1.NotasFiscais.Count-1 do
begin
with FormNotasEntrada.ACBrNFe1.NotasFiscais.Items[n].NFe do
begin
for I := 0 to Det.Count-1 do
begin
with Det.Items[I] do
begin
with FormLerXml.SqlUpdatePro do
begin
close;
sql.clear;
sql.add('update produtos, preentraitens set qtdun = qtdun + qtde');
sql.add('where codbarras = :cod');
ParamByName('cod').Value := Prod.cEAN;
ExecSQL;
end;
end;
end;
end;
end;
end;

A estrutura de minha tabela produtos:

CREATE TABLE bancodados.produtos (
ProID int(11) NOT NULL AUTO_INCREMENT,
codbarras varchar(14) DEFAULT NULL,
Produto varchar(65) DEFAULT NULL,
CodUni varchar(3) DEFAULT NULL,
QtdUn decimal(9, 2) DEFAULT NULL,
notaentrada int(11) DEFAULT NULL,
Comis decimal(9, 2) DEFAULT NULL,
DescMax decimal(9, 2) DEFAULT NULL,
PrecoCompr double(9, 2) DEFAULT NULL,
Margen double(9, 2) DEFAULT NULL,
PrecoVendapr double(9, 2) DEFAULT NULL,
PrecoAtacad double(9, 2) DEFAULT NULL,
NCMprod varchar(8) DEFAULT NULL,
DataCadastr date DEFAULT NULL,
EstoqMin decimal(9, 3) DEFAULT NULL,
QtdCaixa double(9, 2) DEFAULT NULL,
CodBarCaixa varchar(14) DEFAULT NULL,
CodigoAnp varchar(9) DEFAULT NULL,
QtdeAtacad decimal(9, 3) DEFAULT NULL,
CustoMedi decimal(9, 2) DEFAULT NULL,
EstocMax decimal(9, 3) DEFAULT NULL,
RegistroMSau bigint(20) DEFAULT NULL,
Cestpro varchar(8) DEFAULT NULL,
Cstpro varchar(4) DEFAULT NULL,
CFOPpro varchar(4) DEFAULT NULL,
MargApraz double(9, 2) DEFAULT NULL,
TotalProd double(9, 2) DEFAULT NULL,
CodNot int(11) DEFAULT NULL,
NumCaix double(9, 2) DEFAULT NULL,
ValorUnidade double(9, 2) DEFAULT NULL,
CodIten int(11) DEFAULT NULL,
NumIten int(11) DEFAULT NULL,
UndFrac varchar(5) DEFAULT NULL,
QtdeFrac double(18, 2) DEFAULT NULL,
Ativos varchar(1) DEFAULT NULL,
ValorCaix double(9, 2) DEFAULT NULL,
Grup varchar(30) DEFAULT NULL,
Marc varchar(30) DEFAULT NULL,
Codproduto int(11) DEFAULT NULL,
prook varchar(2) DEFAULT NULL,
PRIMARY KEY (ProID)
)
ENGINE = INNODB,
AUTO_INCREMENT = 825,
AVG_ROW_LENGTH = 16384,
CHARACTER SET latin1,
COLLATE latin1_swedish_ci;
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

04/11/2018

também não sei o que está acontecendo. não reconheço essa forma de update:
update produtos, preentraitens 
utilizando duas tabelas sem qualquer relacionamento explícito entre elas. será que não é esse o problema?

se fosse no SQL Server eu faria assim (supondo que todos os itens já estivessem gravados na tabela preentraitens):
function updateproexistente() : string;
var
  n, I : integer;
begin
  with FormLerXml.SqlUpdatePro do
  begin
    close;
    sql.clear;
    sql.add('update p set p.qtde = p.qtde + pit.qtdun');
    sql.add('from preentraitens pit');
    sql.add('inner join produtos p on p.prodid = pit.prodid');
    sql.add('where pit.numnota = :notafiscal');
  end;

  for n := 0 to FormNotasEntrada.ACBrNFe1.NotasFiscais.Count-1 do
  begin
    with FormLerXml.SqlUpdatePro do
    begin
      ParamByName('notafiscal').Value := FormNotasEntrada.ACBrNFe1.NotasFiscais.Items[n].NFe.Ide.nNF;
      ExecSQL;
    end;
  end;
end;
Desta forma precisa do laço somente nas notas.
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

04/11/2018

também não sei o que está acontecendo. não reconheço essa forma de update:
update produtos, preentraitens
utilizando duas tabelas sem qualquer relacionamento explícito entre elas. será que não é esse o problema?

se fosse no SQL Server eu faria assim (supondo que todos os itens já estivessem gravados na tabela preentraitens):
function updateproexistente() : string;
var
  n, I : integer;
begin
  with FormLerXml.SqlUpdatePro do
  begin
    close;
    sql.clear;
    sql.add('update p set p.qtde = p.qtde + pit.qtdun');
    sql.add('from preentraitens pit');
    sql.add('inner join produtos p on p.prodid = pit.prodid');
    sql.add('where pit.numnota = :notafiscal');
  end;
 
  for n := 0 to FormNotasEntrada.ACBrNFe1.NotasFiscais.Count-1 do
    with FormLerXml.SqlUpdatePro do
    begin
      ParamByName('notafiscal').Value := FormNotasEntrada.ACBrNFe1.NotasFiscais.Items[n].NFe.Ide.nNF;
      ExecSQL;
    end;

end;
Desta forma precisa do laço somente nas notas.
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Amigo Emerson.
Muito obrigado por sua dedicação em me ajudar.

Eu fiz de acordo com a sua ultima dica e tambem o resultado foi o mesmo.
Uma observação:
Eu criei uma tigger no sql para ser disparado no insert da tabela preentraitens

Procedimento
DELIMITER //
CREATE PROCEDURE `SP_AtualizaEstoque`( codbar varchar(20), `qtde_entra` decimal(9,2))
BEGIN
declare contador int(11);

SELECT count(*) into contador FROM produto WHERE codbarras = codbar;

IF contador > 0 THEN
UPDATE produtos SET QtdUn=QtdUn + qtde_entra
WHERE codbarras = codbar;
ELSE
INSERT INTO produtos (QtdUn, codbarras) values (qtde_entra, codbar);
END IF;
END //
DELIMITER ;

Tigger
DELIMITER //
CREATE TRIGGER `TRG_EntradaProduto_AI` AFTER INSERT ON `preentraitens`
FOR EACH ROW
BEGIN
CALL SP_AtualizaEstoque (new.Codbarpro, new.qtde);
END //
DELIMITER ;

Funcionou beleza para produtos que tem cod barras, pois fiz a referencia pelo cod barras, mais e produtos que não tem cod barras ??
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Amigo
Consegui resolver meu problema da seguinte forma:
Criei 2 procedimento diretamente no banco de dados
Um chamado atualiza_estoque_por_codbarras

PROCEDURE bancodados.SP_atualiza_estoque_por_codbarras( `cod_barras` varchar(15), `qtde_comprada` decimal(9,2))
BEGIN
declare contador int(11);

SELECT count(*) into contador FROM produtos WHERE Codbarras = cod_barras;

IF contador > 0 THEN
UPDATE produtos SET QtdUn=QtdUn + qtde_comprada
WHERE codbarras = cod_barras;
ELSE
INSERT INTO produtos (codbarras, QtdUn) values (cod_barras, qtde_comprada);
END IF;
END

Outro chamado atualiza_estoque_por_descricaopro

PROCEDURE bancodados.SP_atualiza_estoque_por_descricaopro( `prod` varchar(40), `qtde_comprada` decimal(9,2))
BEGIN
declare contador int(11);

SELECT count(*) into contador FROM produtos WHERE produto = prod;

IF contador > 0 THEN

UPDATE produtos SET QtdUn=QtdUn + qtde_comprada
WHERE Produto = prod;
ELSE
INSERT INTO produtos (Produto, QtdUn) values (prod, qtde_comprada);
END IF;
END

E criei uma Trigger com duas funções

BEGIN
IF
new.codbarpro > 1 THEN
CALL SP_atualiza_estoque_por_codbarras(new.Codbarpro, new.qtde);
END IF;
IF
new.codbarpro < 1 THEN
CALL SP_atualiza_estoque_por_descricaopro (new.DescPro, new.qtde);
END IF;
END

Se o produto que entra o cod barras é o mesmo que ja tem entao update na quant
Se nao tem codigo barras mais a descrição do produto ja tem entao update na qunt
E posso fazer mais um procedimento que peque o nome do fornecedor e o codigo interno do produto que vem do fornecedor, este ainda vou testar, mais por enquanto essa trigger que criei estar funcionando beleza

Então amigo lhe agradeço muito pela ajuda.
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

04/11/2018

Ótimo que você conseguiu resolver.
Mas sugiro uma pequena alteração, para que toda a manipulação do estoque seja feita num único local.
******************************
* PROCEDIMENTO
******************************
DELIMITER //
PROCEDURE bancodados.SP_atualiza_estoque(cod_barras varchar(15), desc_produto varchar(40), qtde_comprada decimal(9,2))
BEGIN
	declare intProID int(11);

	SELECT ProID into intProID FROM produtos
	WHERE (trim(coalesce(cod_barras,''))>'' and codbarras = cod_barras) OR (trim(coalesce(desc_produto,''))>'' and Produto = desc_produto);

	IF IsNull(intProID) THEN
		INSERT INTO produtos (codbarras, produto, QtdUn) values (cod_barras, desc_produto, qtde_comprada);
	ELSE
		UPDATE produtos SET QtdUn = QtdUn + qtde_comprada
		WHERE ProdID = intProID;
	END IF;
END //
DELIMITER ;


******************************
* TRIGGER
******************************
DELIMITER //
CREATE TRIGGER TRG_EntradaProduto_AI AFTER INSERT ON preentraitens
FOR EACH ROW
BEGIN
	CALL SP_AtualizaEstoque (new.Codbarpro, new.DescPro, new.qtde);
END //
DELIMITER ;
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Valeu amigo vou testar aqui e posto o resultado.
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018



Amigo fiz as alterações como vc citou e estar funcionando.
Agradeço muito sua ajuda.
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Amigo Emerson.
Agora que eu fui prestar atenção, depois que coloquei as mudanças na trigger como vc fez ai.
Observei que na tabela produtos só estar sendo gravado o ProID, codbarras, Descrição, e a qtdun o restante dos campos nao estão sendo gravados, quando entra novos itens.

Como mostra a imagem abaixo

https://uploaddeimagens.com.br/imagens/sem_titulo-png-cdcec673-825b-43e9-9413-0167be6a5709
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Eu acho que eu tenho que ter é uma tabela para o estoque e outra p produtos .
Não seria isso ??
GOSTEI 0
Jean Carlos

Jean Carlos

04/11/2018

Já entendi o que estar ocorrendo.
Estar ocorrendo o seguinte com a minha trigger também estava dando isso.
Quando a tabela preentraitens dar o insert, o trigger é acionado e ja grava na tabela produtos o codpro, codbarras, produto, qtdun, fazendo isso,
a minha função no delphi que verifica se o produto ja estar cadastrado é anulada e ele nao grava mais novos itens na tabela produtos
Então fiz uma mudança no procedimento

CREATE DEFINER = 'root'@'localhost'
PROCEDURE bancodados.SP_atualiza_estoque(cod_barras varchar(15), desc_produto varchar(40), qtde_comprada decimal(9,2))
BEGIN
declare intCodPro int(11);

SELECT Codproduto into intCodPro FROM produtos
WHERE (trim(coalesce(cod_barras,''))>'' and codbarras = cod_barras) OR (trim(coalesce(desc_produto,''))>'' and Produto = desc_produto);

IF IsNull(intCodPro) THEN
BEGIN
END;
ELSE
UPDATE produtos SET QtdUn = QtdUn + qtde_comprada
WHERE Codproduto = intCodPro;
END IF;
END

Retirei apenas a parte onde ele insere novos itens, pois esta função eu faço pelo delphi mesmo em uma Tfdquery
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

04/11/2018

Então corrija o IF:
PROCEDURE bancodados.SP_atualiza_estoque(cod_barras varchar(15), desc_produto varchar(40), qtde_comprada decimal(9,2))
BEGIN
	declare intCodPro int(11);

	SELECT Codproduto into intCodPro FROM produtos
	WHERE (trim(coalesce(cod_barras,''))>'' and codbarras = cod_barras) OR (trim(coalesce(desc_produto,''))>'' and Produto = desc_produto);

	IF NOT IsNull(intCodPro) THEN
		UPDATE produtos SET QtdUn = QtdUn + qtde_comprada
		WHERE Codproduto = intCodPro;
	END IF;
END


GOSTEI 0
POSTAR