Atualizar valores de tabelas pai x filho

Porque pesar o banco com i/o em disco a cada consulta?

Não há como passar parâmetros para um trigger, a não ser o valor das colunas do registro da tabela a processar.

Fique tranquilo e não pense nisso agora, por volta das 17h30 com trabalhar nesse tarefa.

Mas é possivel fazer os calculos na consulta?

Eu pensei que o SC tinha alguma opção nativa pra facilitar esse tipo de operação

Meus sinceros agradecimentos.

Como prometido, segue exemplo completo e funcional explicando a praticidade e segurança das triggers.

PARTE 1 : MODELAGEM

CREATE DATABASE IF NOT EXISTS treino /*!40100 DEFAULT CHARACTER SET utf8 */;
USE treino;
– MySQL dump 10.13 Distrib 5.6.13, for Win32 (x86)

– Host: 192.168.25.7 Database: treino


– Server version 5.1.61

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT /;
/
!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS /;
/
!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION /;
/
!40101 SET NAMES utf8 /;
/
!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE /;
/
!40103 SET TIME_ZONE=’+00:00’ /;
/
!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 /;
/
!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 /;
/
!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO’ /;
/
!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


– Table structure for table mat_prima

DROP TABLE IF EXISTS mat_prima;
/*!40101 SET @saved_cs_client = @@character_set_client /;
/
!40101 SET character_set_client = utf8 */;
CREATE TABLE mat_prima (
id_materia_prima int(11) NOT NULL AUTO_INCREMENT,
desc_materia_prima varchar(100) DEFAULT NULL,
genero_materia_prima varchar(45) DEFAULT NULL,
preco_compra_mp decimal(10,3) DEFAULT NULL,
icms_mp decimal(10,2) DEFAULT NULL,
pis_mp decimal(10,2) DEFAULT NULL,
cofins_mp decimal(10,2) DEFAULT NULL,
ipi_mp decimal(10,2) DEFAULT NULL,
ii_mp decimal(10,2) DEFAULT NULL,
frete_mp decimal(10,2) DEFAULT NULL,
comissao_mp decimal(10,2) DEFAULT NULL,
preco_final_mp decimal(10,3) DEFAULT NULL,
PRIMARY KEY (id_materia_prima)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

/!50003 SET sql_mode = @saved_sql_mode / ;
/
!50003 SET character_set_client = @saved_cs_client / ;
/
!50003 SET character_set_results = @saved_cs_results / ;
/
!50003 SET collation_connection = @saved_col_connection / ;
/
!50003 SET @saved_cs_client = @@character_set_client / ;
/
!50003 SET @saved_cs_results = @@character_set_results / ;
/
!50003 SET @saved_col_connection = @@collation_connection / ;
/
!50003 SET character_set_client = utf8 / ;
/
!50003 SET character_set_results = utf8 / ;
/
!50003 SET collation_connection = utf8_general_ci / ;
/
!50003 SET @saved_sql_mode = @@sql_mode / ;
/
!50003 SET sql_mode = ‘’ / ;
DELIMITER ;;
/
!50003 CREATE
/ /!50017 DEFINER=root@%/ /!50003 TRIGGER mat_prima_AUPD AFTER UPDATE ON mat_prima FOR EACH ROW
begin
UPDATE prod_matprima SET total_pf=per_pf
NEW.preco_final_mp WHERE id_mat_prima=NEW.id_materia_prima;
END /;;
DELIMITER ;
/
!50003 SET sql_mode = @saved_sql_mode / ;
/
!50003 SET character_set_client = @saved_cs_client / ;
/
!50003 SET character_set_results = @saved_cs_results / ;
/
!50003 SET collation_connection = @saved_col_connection */ ;


– Table structure for table prod_acabado

DROP TABLE IF EXISTS prod_acabado;
/*!40101 SET @saved_cs_client = @@character_set_client /;
/
!40101 SET character_set_client = utf8 /;
CREATE TABLE prod_acabado (
id_produto_final int(11) NOT NULL AUTO_INCREMENT,
desc_pf varchar(60) DEFAULT NULL,
genero_pf varchar(45) DEFAULT NULL,
custo_total_pf decimal(10,2) DEFAULT NULL,
PRIMARY KEY (id_produto_final)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
/
!40101 SET character_set_client = @saved_cs_client */;


– Table structure for table prod_matprima

DROP TABLE IF EXISTS prod_matprima;
/!40101 SET @saved_cs_client = @@character_set_client /;
/
!40101 SET character_set_client = utf8 /;
CREATE TABLE prod_matprima (
id_prod_acabado int(11) NOT NULL,
id_mat_prima varchar(45) NOT NULL,
per_pf decimal(10,4) DEFAULT NULL,
total_pf decimal(10,2) DEFAULT NULL,
PRIMARY KEY (id_prod_acabado,id_mat_prima)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/
!40101 SET character_set_client = @saved_cs_client /;
/
!50003 SET @saved_cs_client = @@character_set_client / ;
/
!50003 SET @saved_cs_results = @@character_set_results / ;
/
!50003 SET @saved_col_connection = @@collation_connection / ;
/
!50003 SET character_set_client = utf8 / ;
/
!50003 SET character_set_results = utf8 / ;
/
!50003 SET collation_connection = utf8_general_ci / ;
/
!50003 SET @saved_sql_mode = @@sql_mode / ;
/
!50003 SET sql_mode = ‘’ / ;
DELIMITER ;;
/
!50003 CREATE
/ /!50017 DEFINER=root@%/ /!50003 TRIGGER prod_matprima_AINS AFTER INSERT ON prod_matprima FOR EACH ROW
begin
UPDATE prod_acabado
SET custo_total_pf=
(SELECT SUM(total_pf)
FROM prod_matprima
WHERE id_prod_acabado=NEW.id_prod_acabado)
WHERE id_produto_final=NEW.id_prod_acabado;
end /;;
DELIMITER ;
/
!50003 SET sql_mode = @saved_sql_mode / ;
/
!50003 SET character_set_client = @saved_cs_client / ;
/
!50003 SET character_set_results = @saved_cs_results / ;
/
!50003 SET collation_connection = @saved_col_connection / ;
/
!50003 SET @saved_cs_client = @@character_set_client / ;
/
!50003 SET @saved_cs_results = @@character_set_results / ;
/
!50003 SET @saved_col_connection = @@collation_connection / ;
/
!50003 SET character_set_client = utf8 / ;
/
!50003 SET character_set_results = utf8 / ;
/
!50003 SET collation_connection = utf8_general_ci / ;
/
!50003 SET @saved_sql_mode = @@sql_mode / ;
/
!50003 SET sql_mode = ‘’ / ;
DELIMITER ;;
/
!50003 CREATE
/ /!50017 DEFINER=root@%/ /!50003 TRIGGER prod_matprima_AUPD AFTER UPDATE ON prod_matprima FOR EACH ROW
begin
UPDATE prod_acabado
SET custo_total_pf=
(SELECT SUM(total_pf)
FROM prod_matprima
WHERE id_prod_acabado=NEW.id_prod_acabado)
WHERE id_produto_final=NEW.id_prod_acabado;
end /;;
DELIMITER ;
/
!50003 SET sql_mode = @saved_sql_mode / ;
/
!50003 SET character_set_client = @saved_cs_client / ;
/
!50003 SET character_set_results = @saved_cs_results / ;
/
!50003 SET collation_connection = @saved_col_connection / ;
/
!50003 SET @saved_cs_client = @@character_set_client / ;
/
!50003 SET @saved_cs_results = @@character_set_results / ;
/
!50003 SET @saved_col_connection = @@collation_connection / ;
/
!50003 SET character_set_client = utf8 / ;
/
!50003 SET character_set_results = utf8 / ;
/
!50003 SET collation_connection = utf8_general_ci / ;
/
!50003 SET @saved_sql_mode = @@sql_mode / ;
/
!50003 SET sql_mode = ‘’ / ;
DELIMITER ;;
/
!50003 CREATE
/ /!50017 DEFINER=root@%/ /*!50003 TRIGGER prod_matprima_ADEL AFTER DELETE ON prod_matprima FOR EACH ROW
begin
UPDATE prod_acabado
SET custo_total_pf=
(SELECT SUM(total_pf)
FROM prod_matprima
WHERE id_prod_acabado=OLD.id_prod_acabado)
WHERE id_produto_final=OLD.id_prod_acabado;
end /;;
DELIMITER ;
/
!50003 SET sql_mode = @saved_sql_mode / ;
/
!50003 SET character_set_client = @saved_cs_client / ;
/
!50003 SET character_set_results = @saved_cs_results / ;
/
!50003 SET collation_connection = @saved_col_connection */ ;


– Dumping events for database ‘treino’


– Dumping routines for database ‘treino’

/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE /;
/
!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS /;
/
!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS /;
/
!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT /;
/
!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS /;
/
!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION /;
/
!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

– Dump completed on 2014-01-26 0:37:51

Para Download das aplicações (Importe como aplicações em um projeto já existente):

http://iw.servehttp.com:86/ftp/sc_201401260043_bkp_Treino.zip

  • Nota: O dwnload do exemplo não estará disponível por muito tempo.

Acessando o exemplo:

http://iw.servehttp.com:86/sc/7.1/app/Treino/form_prod_acabado

Tela do exemplo:

Explicação:

Triggers:

Tabela prod_matprima (tabela de ligação das matérias primas ao produto).
Gatilho 1:
Após Inserir, alterar ou excluir é executado um update em produtos baseado em um select sum em todas as matérias primas relacionadas a esse produto.

Tabela materia_prima
Gatilho 2:
Após alterar é executado um update em prod_matprima de todos registros relacionados a essa matéria prima recalculando o custo_total. O update em prod_matprima aciona o gatilho 1 que por sua vez atualiza o custo final do produto. (Encadeamento de gatilhos).

Aplicação form_mat_prima

Evento Onvalidate:

  • Verifica se for deleção e se a matéria prima está em uso, não permite excluir.

Aplicação form_produto_acabado (Mestre/Detalhe):
Possui um detalhe apontando para form_prod_matprima utilizando o id do produto como referência de filtro de registros para o detalhe.

Aplicação form_prod_matprima (Detalhe do cadastro de produtos):
Evento Ajax no campo quantidade:

  • Busca o custo da matéria prima para sua unidade padrão e calcula pela quantidade o custo de utilização dessa matéria no produto corrente.

Método PHP AtualizaProduto:
-Busca o custo final do produto e apresenta na janela relacionada do formulário mestre.

Evento OnLoadRecord:
-Executa AtualizaProduto quando da inserção ou alteração da linha detalhe.

Evento OnAfterDelete:

  • Executa AtualizaProduto quando da deleção da linha detalhe

O exemplo levou 1,5 horas para ser confeccionado, e demonstra como eh simples e prático usar triggers num processo de atualizações que são disparados automaticamente, ganhando performance no processo, pois as atualizações são disparadas pelo próprio banco de dados, não trafegando dados entre o php e o banco, ganha-se segurança e integridade das informações, facilita manutenção e pode-se aplicar outras plataformas (tipo apps mobile) que os procedimentos serão os mesmos ganhando reprogramação.

O Exemplo é uma demonstração e não sei se vai ser utilizado exatamente como está para atender ao nosso colega criador desse tópico, pois houve dúvidas quanto a estrutura de dados, cálculos a executar e na imagem da tela postada aqui, mas acredito que estudando o exemplo facilmente chegará ao resultado esperado quando aplicar o conceito em seu projeto.

***Nota: O custo do produto que usei como exemplo, foi calculado em cima das matérias primas cujos os preços e unidades de medição foram pesquisados no site do Pão de Açúcar, e representa o custo real aproximado para confecção de um BOLO DE CENOURA.

Links de Ajuda

http://www.tudogostoso.com.br/receita/23-bolo-de-cenoura.html

http://www.paodeacucar.com.br/

http://pt.wikipedia.org/wiki/Pesos_e_medidas_culinárias

Haroldo, primeiramente agradeço a sua ajuda! Ficou muito bom seu exemplo.

Realmente é isso que estou precisando… já estou modificando algumas coisas a partir do seu modelo para incluir em meu projeto.

Só peço por gentileza aos moderadores para não fechar o tópico, eu vou fazer os testes e retorno o mais breve possível.

Novamente agradeço.

Não se preocupe, um tópico nunca eh fechado aqui. O que pedimos e que retorne com sua experiência quanto a solução aplicada e se seu problema foi resolvido.

Haroldo.

Fiz as adaptações para o meu projeto… e esta funcionando parcialmente.

Estou com problema na Trigger da matéria prima, ao ser acionada ela altera o valor final dos produtos acabados, deixando todos com os mesmos valores…

Eu segui a risca suas dicas, ontem e hoje, já tentei de tudo antes de recorrer a ti… mas não estou conseguindo… fazer isso funcionar…
o restante esta tudo ok…

Por favor, me ajude

Trigger para atualizar materias primas

UPDATE prod_mat
SET total_pf=per_pf*NEW.preco_final_mp
WHERE id_mat_prima=NEW.id_materia_prima

Gratidão!

Qual o nome da coluna id da tabela materia_prima?

id_materia_prima

Se fez como demonstrei no exemplo tem que funcionar igual.

Você deve ter feito algo diferente.

Eu já revisei o projeto diversas vezes esta do mesmo modo que voce ensinou…

O problema esta mesmo na Trigger da Materia Prima ele atualiza todos os produtos mas com o mesmo preço.

As demais Triggers funcionam normalmente.

Bom vou da um tempo… e vou tentar refazer tudo pra ver se acerto.

Agradeço!

Al alterar um registro de matéria prima, esta aciona a trigger after update que por si recalcula (faz update) em todos os registos cujo oid seja dessa materia prima em prod_mat,

Alterar materia prima não executa update em produto.

Reveja a trigger after update em prod_mat eh essa que executa a alteração nos produtos.

Haroldo.

Meus sinceros agradecimentos.

Agora esta funcionando ok… realmente o problema era na Trigger After Update ( tabela: mat_prod )

Surgiu uma duvida em relação a tela de cadastro de produto acabado, por favor preciso de mais uma ajuda…

Ao cadastrar um produto acabado, esse produto vai em uma determinada embalagem. (1 para muitos)

Eu fiz o cadastro de embalagem do modo que você me ensinou aqui, pois cada embalagem esta vinculada a N matérias primas…
esta funcionando perfeitamente.

Minha duvida é a seguinte.

Na tela de cadastro de produto acabado, eu fiz um mestre / detalhe para as embalagens…

Pergunta: É possível retornar as embalagens cadastradas com checkbox?
Ao selecionar uma embalagem, o sistema deve fazer o seguinte calculo automatico, semelhante a Trigger materia prima…

custo_total_produto_acabado * volume_da_embalagem + preco_embalagem_selecionada

Caso ajude segue imagem.

Antes: http://lucheti.com.br/cadastro_pf_01.jpg
(feito através de iframe , porem era necessario clicar em calcular)

Depois: http://lucheti.com.br/cadastro_pf_02.jpg

Devo um favor a ti!

Gratidão.

AI tem que mexer novamente na modelagem.
em produtos acabados você deve ter:

custo_total_materias_primas (esse será o calculados pelas triggers)

Se for apenas uma embalagem por produto:

criar id_embalagem na tabela de produtos.

Na app form de produtos, criar um checkbox para o campo id_embalagem e em lookup automatico jogar o select.

criar campo custo_final_produto.

em onbeforeinsert e update, fazer sc_lookup e pegar o vaor da embalagem e somar calcular custo_final_produto = custo_total_materias_primas + custo_embalagem.

criar trigger para embalagens, quando alterar produto fazer update em produto baseado no calculo anterior.

nas triigger prod_mat prever o calculo anterior.

você aprendendo o conceito das triggers conseguirá ir em frente.

Haroldo.

Eu entendi parcialmente a sua solução… só não ficou claro como vou salvar o valor de cada embalagem selecionada?

Na imagem abaixo, eu fiz um select e a cada linha o código criava um campo de texto dinamicamente…
http://lucheti.com.br/cadastro_pf_01.jpg

São N embalagens para 1 produto.

No caso eu devo criar um id_embalagem na tabela PRODUTOS e também o campo custo_embalagem (para salvar o valor) ?

Fiz uma pergunta no meu post anterior.

Não esta claro como você aponta uma embalagem para o produto.

Cada produto tem apenas uma única embalagem?
Cada embalagem tem apenas um único produto?
O Custo do produto esta diretamente relacionado a embalagem? Acredito que sim, somente quando um produto tem embalagem única e própria, pois geralmente o custo da embalagem é apreciado no faturamento deste produto.

Na sua imagem, tem um campo input na linha de cada tipo de embalagem o que vai nele?

Cada produto tem apenas uma única embalagem?
R: Não. O produto pode ter inúmeras embalagens

Cada embalagem tem apenas um único produto?
R: Cada embalagem tem inúmeras matérias primas que a compõe. (por exemplo Frasco 1L, vai rotulo, etiqueta, caixa de papelão… o próprio frasco…) cada embalagem pode ir para N produtos.

O Custo do produto esta diretamente relacionado a embalagem?
R: O valor da embalagem é calculado atraves da quantidade de materias primas que a compõe. O mesmo ocorre com o produto.
O custo do produto, acredito, não esta relacionado a embalagem, porém ao selecionar uma embalagem, é formado outro custo mas não para o produto acabado e nem para a embalagem cadastrada, neste caso é um outro valor que deve ser armazenado.

Na sua imagem, tem um campo input na linha de cada tipo de embalagem o que vai nele?
R: O input recebe o valor de cada embalagem selecionada (a resposta acima)

Agradeço!

Eh acho que não estou conseguindo racionar bem hoje.

Tudo bem…

Mas como eu faço um checkbox pegando de uma tabela 4 colunas e acrescentando um input text?

Por exemplo:
ID | Produto | Preço compra | Custo

Semelhante a imagem abaixo…
http://lucheti.com.br/cadastro_pf_01.jpg

Sobre a modelagem eu fiz uma outra tabela ( prod_emb ) no qual armazena o id_embalagem, id_produto_acabado, quant e total

Na hora do cadastro, funciona, esta tudo amarrrado… ainda nao fiz a Trigger para atualizar os valores na hora do insert / update / delete…

Agradeço