Delphi ajuda no Update do estoque
04/11/2018
0
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
Posts
05/11/2018
Emerson Nascimento
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;
05/11/2018
Jean Carlos
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
06/11/2018
Emerson Nascimento
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;
06/11/2018
Jean Carlos
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;
06/11/2018
Emerson Nascimento
update produtos, preentraitens
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;
06/11/2018
Emerson Nascimento
update produtos, preentraitens
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;
06/11/2018
Jean Carlos
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 ??
06/11/2018
Jean Carlos
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.
07/11/2018
Emerson Nascimento
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 ;
07/11/2018
Jean Carlos
Amigo fiz as alterações como vc citou e estar funcionando.
Agradeço muito sua ajuda.
07/11/2018
Jean Carlos
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
07/11/2018
Jean Carlos
Não seria isso ??
07/11/2018
Jean Carlos
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
08/11/2018
Emerson Nascimento
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
Clique aqui para fazer login e interagir na Comunidade :)