Atualizar valores de tabelas pai x filho

Estrutura:

Tabela Materia Prima

id_materia_prima
desc_materia_prima
genero_materia_prima
preco_compra_mp
icms_mp
pis_mp
cofins_mp
ipi_mp
ii_mp
frete_mp
comissao_mp
preco_final_mp

=======================

Produto:
id_produto_final
desc_pf
genero_pf
custo_total_pf

=========================

ProdutoXMatPrima:
id_produto_final
id_materia_prima
per_pf
preco_mp
total_pf

Agora nos demonstre as regras do processo, exemplifique um calculo:

// preco da materia prima
$preco_total_mp_01 = {preco_mp_01};

// quantidade de materia prima
$per_pf_01 = {per_pf_01};

// calculo da materia prima
$valor_total_mp_01 = $preco_total_mp_01 * $per_pf_01 / 100;

// resposta
{total_pf_01} = $valor_total_mp_01;

//calculo produto final
$valor_produto_final = {total_pf_01} + {total_pf_02} + {total_pf_03} + {total_pf_04} + {total_pf_05} + {total_pf_06} + {total_pf_07} + {total_pf_08} + {total_pf_09} + {total_pf_10}

Segue imagem da aplicação, caso ajude.

http://lucheti.com.br/cadastro_pf.jpg

suas telas terão que mudar caso mude a estrutura, tudo bem?

E terá que criar uma trigger para inclusão e alteração de produtos também.

Tudo bem… se resolver o problema… ok… rs

Mas qual a sua ideia?

Minha ideia eh criar o exemplo completo para você, só preciso achar 1 hora na minha tarde de hoje para fazer isso.

bom… não quero te atrapalhar… agradeço mesmo a ajuda.

eu imaginei que dava para fazer a Trigger mais ou menos assim

TRIGGER atualiza_mp AFTER UPDATE ON cadastro_materia_prima
FOR EACH ROW UPDATE cadastro_produto_final
SET preco_mp_01 = (valor_da_materia_atualizada) WHERE id_materia_prima = (id_materia_prima)

e depois faz o calculo e atualiza a tabela de produto final

se der para fazer assim acredito que resolve… o problema é que eu não consigo pegar o ID da matéria atualizada… alem disso eu tenho tambem uma tela onde o usuario pode alterar N matérias primas de uma so vez.

Te apresento o resultado final assim que concluir a tarefa, até lá vá fazendo outras coisas.

estava pensando aqui… sera que na hora de fazer uma consulta do produto final

nao tem como ele fazer os calculos de tudo antes de exibir os dados?

uma duvida tambem… nao tem como passar parametros/variavel para a Trigger?

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.