RA
Salvar 2 Datalhes - Mestre/Detalhe
Pessoal, bom dia. Fiz uma mestre detalhe com 2 detalhes, estou com um problema para salvar os dados, ele salva 2x. Como posso implementar uma rotina para salvar os 2 detalhes uma vês só?
- <?php
- /**
- * TabelaVendasForm Master/Detail
- * @author <your name here>
- */
- class TabelaVendasForm extends TPage
- {
- protected $form; // form
- protected $detail_list;
- /**
- * Page constructor
- */
- public function __construct()
- {
- parent::__construct();
- // creates the form
- $this->form = new BootstrapFormBuilder('form_TabelaVendas');
- $this->form->setFormTitle('Dados Principais');
- // master fields
- $id = new TEntry('id');
- $cadastro_id = new TDBUniqueSearch('cadastro_id', 'projeto', 'Cadastro', 'id', 'nome');
- $data_venda = new TDate('data_venda');
- $vendedor_id = new TDBUniqueSearch('vendedor_id', 'projeto', 'Cadastro', 'id', 'nome');
- $centro_custo = new TCombo('centro_custo');
- $tipo_venda = new TCombo('tipo_venda');
- // detail fields - PRODUTOS
- $detail_id = new THidden('detail_id');
- $detail_tabela_produtos_id = new TDBUniqueSearch('detail_tabela_produtos_id', 'projeto', 'TabelaProdutos', 'id', 'nome');
- $detail_qtd_produto = new TEntry('detail_qtd_produto');
- $detail_valor_produto = new TEntry('detail_valor_produto');
- $detail_desconto_produto = new TEntry('detail_desconto_produto');
- $centro_custo->addItems( ['Clínica' => 'Clínica', 'Piscina' => 'Piscina'] );
- $tipo_venda->addItems( ['Venda Direta' => 'Venda Direta', 'Orçamento' => 'Orçamento'] );
- // detail fields - SERVIÇOS
- $detail2_id = new THidden('detail2_id');
- $detail2_tabela_servicos_id = new TDBUniqueSearch('detail2_tabela_servicos_id', 'projeto', 'TabelaServicos', 'id', 'nome');
- $detail2_qtd_servico = new TEntry('detail2_qtd_servico');
- $detail2_valor_servico = new TEntry('detail2_valor_servico');
- $detail2_desconto_servico = new TEntry('detail2_desconto_servico');
- if (!empty($id))
- {
- $id->setEditable(FALSE);
- }
- // master fields - PRODUTOS
- $this->form->addFields( [new TLabel('Id')], [$id] );
- $this->form->addFields( [new TLabel('Cadastro Id')], [$cadastro_id] );
- $this->form->addFields( [new TLabel('Data Venda')], [$data_venda] );
- $this->form->addFields( [new TLabel('Vendedor Id')], [$vendedor_id] );
- $this->form->addFields( [new TLabel('Centro Custo')], [$centro_custo] );
- $this->form->addFields( [new TLabel('Tipo Venda')], [$tipo_venda] );
- // detail fields - PRODUTOS
- $this->form->addContent( ['<h4>Produtos</h4><hr>'] );
- $this->form->addFields( [$detail_id] );
- $this->form->addFields( [new TLabel('Tabela Produtos Id')], [$detail_tabela_produtos_id] );
- $this->form->addFields( [new TLabel('Qtd Produto')], [$detail_qtd_produto],
- [new TLabel('Valor Produto')], [$detail_valor_produto],
- [new TLabel('Desconto Produto')], [$detail_desconto_produto] );
- $add = TButton::create('add', [$this, 'onSaveDetail'], 'Adicionar Produtos', 'fa:save');
- $this->form->addFields( [], [$add] )->style = 'background: whitesmoke; padding: 5px; margin: 1px;';
- $this->detail_list = new BootstrapDatagridWrapper(new TQuickGrid);
- $this->detail_list->style = "min-width: 700px; width:100%;margin-bottom: 10px";
- $this->detail_list->setId('TabelaVendas_list');
- // items - PRODUTOS
- $this->detail_list->addQuickColumn('Tabela Produtos Id', 'tabela_produtos_id', 'center', 100);
- $this->detail_list->addQuickColumn('Qtd Produto', 'qtd_produto', 'center', 100);
- $this->detail_list->addQuickColumn('Valor Produto', 'valor_produto', 'center', 100);
- $this->detail_list->addQuickColumn('Desconto Produto', 'desconto_produto', 'center', 100);
- $st = $this->detail_list->addQuickColumn('Subtotal', '={qtd_produto} * ({valor_produto} - {desconto_produto})', 'right', 100);
- $format_value = function($value){
- if (is_numeric($value))
- {
- return 'R$ ' . number_format($value, 2, ",", ".");
- }
- };
- $st->setTransformer($format_value);
- $st->setTotalFunction( function($values){
- return array_sum( (array) $values );
- });
- // detail actions - PRODUTOS
- $this->detail_list->addQuickAction( 'Edit', new TDataGridAction([$this, 'onEditDetail']), 'id', 'fa:edit blue');
- $this->detail_list->addQuickAction( 'Delete', new TDataGridAction([$this, 'onDeleteDetail']), 'id', 'fa:trash red');
- $this->detail_list->createModel();
- $panel = new TPanelGroup;
- $panel->add($this->detail_list);
- $panel->getBody()->style = 'overflow-x:auto';
- $this->form->addContent( [$panel] );
- // detail fields - SERVIÇOS
- $this->form->addContent( ['<h4>Serviços</h4><hr>'] );
- $this->form->addFields( [$detail2_id] );
- $this->form->addFields( [new TLabel('Tabela Servicos Id')], [$detail2_tabela_servicos_id] );
- $this->form->addFields( [new TLabel('Qtd Servico')], [$detail2_qtd_servico],
- [new TLabel('Valor Servico')], [$detail2_valor_servico],
- [new TLabel('Desconto Servico')], [$detail2_desconto_servico] );
- $add2 = TButton::create('add2', [$this, 'onSaveDetail2'], 'Adicionar Serviços', 'fa:save');
- $this->form->addFields( [], [$add2] )->style = 'background: whitesmoke; padding: 5px; margin: 1px;';
- $this->detail2_list = new BootstrapDatagridWrapper(new TQuickGrid);
- $this->detail2_list->style = "min-width: 700px; width:100%;margin-bottom: 10px";
- $this->detail2_list->setId('TabelaVendas_list2');
- // items - SERVIÇOS
- $this->detail2_list->addQuickColumn('Tabela Servicos Id', 'tabela_servicos_id', 'left', 100);
- $this->detail2_list->addQuickColumn('Qtd Servico', 'qtd_servico', 'left', 100);
- $this->detail2_list->addQuickColumn('Valor Servico', 'valor_servico', 'left', 100);
- $this->detail2_list->addQuickColumn('Desconto Servico', 'desconto_servico', 'left', 100);
- $st2 = $this->detail2_list->addQuickColumn('Subtotal', '={qtd_servico} * ({valor_servico} - {desconto_servico})', 'right', 100);
- $format_value = function($value){
- if (is_numeric($value))
- {
- return 'R$ ' . number_format($value, 2, ",", ".");
- }
- };
- $st2->setTransformer($format_value);
- $st2->setTotalFunction( function($values){
- return array_sum( (array) $values );
- });
- // detail actions - SERVIÇOS
- $this->detail2_list->addQuickAction( 'Edit', new TDataGridAction([$this, 'onEditDetail2']), 'id', 'fa:edit blue');
- $this->detail2_list->addQuickAction( 'Delete', new TDataGridAction([$this, 'onDeleteDetail2']), 'id', 'fa:trash red');
- $this->detail2_list->createModel();
- $panel = new TPanelGroup;
- $panel->add($this->detail2_list);
- $panel->getBody()->style = 'overflow-x:auto';
- $this->form->addContent( [$panel] );
- // actions - PRODUTO
- $btn = $this->form->addAction( _t('Save'), new TAction([$this, 'onSave']), 'fa:save');
- $btn->class = 'btn btn-sm btn-primary';
- $this->form->addAction( _t('Clear'), new TAction([$this, 'onClear']), 'fa:eraser red');
- // actions - SERVIÇOS
- /*$btn2 = $this->form->addAction( _t('Save2'), new TAction([$this, 'onSave']), 'fa:save');
- $btn2->class = 'btn btn-sm btn-primary';
- $this->form->addAction( _t('Clear2'), new TAction([$this, 'onClear2']), 'fa:eraser red');*/
- // create the page container
- $container = new TVBox;
- $container->style = 'width: 90%';
- // $container->add(new TXMLBreadCrumb('menu.xml', __CLASS__));
- $container->add($this->form);
- parent::add($container);
- }
- public function onClear($param)
- {
- $this->form->clear(TRUE);
- TSession::setValue(__CLASS__.'_items', array());
- TSession::setValue(__CLASS__.'_items2', array());
- $this->onReload2( $param );
- $this->onReload( $param );
- }
- public function onSaveDetail( $param )
- {
- try
- {
- TTransaction::open('projeto');
- $data = $this->form->getData();
- /** validation sample
- if (empty($data->fieldX))
- {
- throw new Exception('The field fieldX is required');
- }
- **/
- $items = TSession::getValue(__CLASS__.'_items');
- $key = empty($data->detail_id) ? 'X'.mt_rand(1000000000, 1999999999) : $data->detail_id;
- $items[ $key ] = array();
- $items[ $key ]['id'] = $key;
- $items[ $key ]['tabela_produtos_id'] = $data->detail_tabela_produtos_id;
- $items[ $key ]['qtd_produto'] = $data->detail_qtd_produto;
- $items[ $key ]['valor_produto'] = $data->detail_valor_produto;
- $items[ $key ]['desconto_produto'] = $data->detail_desconto_produto;
- TSession::setValue(__CLASS__.'_items', $items);
- // clear detail form fields
- $data->detail_id = '';
- $data->detail_tabela_produtos_id = '';
- $data->detail_qtd_produto = '';
- $data->detail_valor_produto = '';
- $data->detail_desconto_produto = '';
- TTransaction::close();
- $this->form->setData($data);
- $this->onReload( $param ); // reload the items
- }
- catch (Exception $e)
- {
- $this->form->setData( $this->form->getData());
- new TMessage('error', $e->getMessage());
- }
- }
- public function onSaveDetail2( $param )
- {
- try
- {
- TTransaction::open('projeto');
- $data = $this->form->getData();
- /** validation sample
- if (empty($data->fieldX))
- {
- throw new Exception('The field fieldX is required');
- }
- **/
- $items2 = TSession::getValue(__CLASS__.'_items2');
- $key = empty($data->detail2_id) ? 'X'.mt_rand(1000000000, 1999999999) : $data->detail2_id;
- $items2[ $key ] = array();
- $items2[ $key ]['id'] = $key;
- $items2[ $key ]['tabela_servicos_id'] = $data->detail2_tabela_servicos_id;
- $items2[ $key ]['qtd_servico'] = $data->detail2_qtd_servico;
- $items2[ $key ]['valor_servico'] = $data->detail2_valor_servico;
- $items2[ $key ]['desconto_servico'] = $data->detail2_desconto_servico;
- TSession::setValue(__CLASS__.'_items2', $items2);
- // clear detail form fields
- $data->detail2_id = '';
- $data->detail2_tabela_servicos_id = '';
- $data->detail2_qtd_servico = '';
- $data->detail2_valor_servico = '';
- $data->detail2_desconto_servico = '';
- TTransaction::close();
- $this->form->setData($data);
- $this->onReload2( $param ); // reload the items
- }
- catch (Exception $e)
- {
- $this->form->setData( $this->form->getData());
- new TMessage('error', $e->getMessage());
- }
- }
- public static function onEditDetail( $param )
- {
- // read session items
- $items = TSession::getValue(__CLASS__.'_items');
- // get the session item
- $item = $items[ $param['key'] ];
- $data = new stdClass;
- $data->detail_id = $item['id'];
- $data->detail_tabela_produtos_id = $item['tabela_produtos_id'];
- $data->detail_qtd_produto = $item['qtd_produto'];
- $data->detail_valor_produto = $item['valor_produto'];
- $data->detail_desconto_produto = $item['desconto_produto'];
- // fill detail fields
- TForm::sendData( 'form_TabelaVendas', $data );
- }
- public static function onEditDetail2( $param )
- {
- // read session items
- $items2 = TSession::getValue(__CLASS__.'_items2');
- // get the session item
- $item2 = $items2[ $param['key'] ];
- $data = new stdClass;
- $data->detail2_id = $item2['id'];
- $data->detail2_tabela_servicos_id = $item2['tabela_servicos_id'];
- $data->detail2_qtd_servico = $item2['qtd_servico'];
- $data->detail2_valor_servico = $item2['valor_servico'];
- $data->detail2_desconto_servico = $item2['desconto_servico'];
- // fill detail fields
- TForm::sendData( 'form_TabelaVendas', $data );
- }
- public static function onDeleteDetail( $param )
- {
- // reset items
- $data = new stdClass;
- $data->detail_tabela_produtos_id = '';
- $data->detail_qtd_produto = '';
- $data->detail_valor_produto = '';
- $data->detail_desconto_produto = '';
- // clear form data
- TForm::sendData('form_TabelaVendas', $data );
- // read session items
- $items = TSession::getValue(__CLASS__.'_items');
- // get detail id
- $detail_id = $param['key'];
- // delete the item from session
- unset($items[ $detail_id ] );
- // rewrite session items
- TSession::setValue(__CLASS__.'_items', $items);
- // delete item from screen
- TScript::create("ttable_remove_row_by_id('TabelaVendas_list', '{$detail_id}')");
- }
- public static function onDeleteDetail2( $param )
- {
- // reset items
- $data = new stdClass;
- $data->detail2_tabela_servicos_id = '';
- $data->detail2_qtd_servico = '';
- $data->detail2_valor_servico = '';
- $data->detail2_desconto_servico = '';
- // clear form data
- TForm::sendData('form_TabelaVendas', $data );
- // read session items
- $items2 = TSession::getValue(__CLASS__.'_items2');
- // get detail id
- $detail2_id = $param['key'];
- // delete the item from session
- unset($items2[ $detail2_id ] );
- // rewrite session items
- TSession::setValue(__CLASS__.'_items2', $items2);
- // delete item from screen
- TScript::create("ttable_remove_row_by_id('TabelaVendas_list2', '{$detail2_id}')");
- }
- public function onReload($param)
- {
- // read session items
- $items = TSession::getValue(__CLASS__.'_items');
- $this->detail_list->clear(); // clear detail list
- if ($items)
- {
- foreach ($items as $list_item)
- {
- $item = (object) $list_item;
- $row = $this->detail_list->addItem( $item );
- $row->id = $list_item['id'];
- }
- }
- $this->loaded = TRUE;
- }
- public function onReload2($param)
- {
- // read session items
- $items2 = TSession::getValue(__CLASS__.'_items2');
- $this->detail2_list->clear(); // clear detail list
- if ($items2)
- {
- foreach ($items2 as $list_item2)
- {
- $item2 = (object) $list_item2;
- $row = $this->detail2_list->addItem( $item2 );
- $row->id = $list_item2['id'];
- }
- }
- $this->loaded = TRUE;
- }
- public function onEdit($param)
- {
- try
- {
- TTransaction::open('projeto');
- if (isset($param['key']))
- {
- $key = $param['key'];
- $object = new TabelaVendas($key);
- $items = TabelaVendasProdutos::where('tabela_vendas_id', '=', $key)->load();
- $session_items = array();
- foreach( $items as $item )
- {
- $item_key = $item->id;
- $session_items[$item_key] = $item->toArray();
- $session_items[$item_key]['id'] = $item->id;
- $session_items[$item_key]['tabela_produtos_id'] = $item->tabela_produtos_id;
- $session_items[$item_key]['qtd_produto'] = $item->qtd_produto;
- $session_items[$item_key]['valor_produto'] = $item->valor_produto;
- $session_items[$item_key]['desconto_produto'] = $item->desconto_produto;
- }
- TSession::setValue(__CLASS__.'_items', $session_items);
- $this->form->setData($object); // fill the form with the active record data
- $this->onReload( $param ); // reload items list
- TTransaction::close(); // close transaction
- }
- else
- {
- $this->form->clear(TRUE);
- TSession::setValue(__CLASS__.'_items', null);
- $this->onReload( $param );
- }
- }
- catch (Exception $e) // in case of exception
- {
- new TMessage('error', $e->getMessage());
- TTransaction::rollback();
- }
- }
- public function onEdit2($param)
- {
- try
- {
- TTransaction::open('projeto');
- if (isset($param['key']))
- {
- $key = $param['key'];
- $object = new TabelaVendas($key);
- $items2 = TabelaVendasServicos::where('tabela_vendas_id', '=', $key)->load();
- $session_items = array();
- foreach( $items2 as $item2 )
- {
- $item_key2 = $item2->id;
- $session_items[$item_key2] = $item2->toArray();
- $session_items[$item_key2]['id'] = $item2->id;
- $session_items[$item_key2]['tabela_servicos_id'] = $item2->tabela_servicos_id;
- $session_items[$item_key2]['qtd_servico'] = $item2->qtd_servico;
- $session_items[$item_key2]['valor_servico'] = $item2->valor_servico;
- $session_items[$item_key2]['desconto_servico'] = $item2->desconto_servico;
- }
- TSession::setValue(__CLASS__.'_items2', $session_items2);
- $this->form->setData($object); // fill the form with the active record data
- $this->onReload2( $param ); // reload items list
- TTransaction::close(); // close transaction
- }
- else
- {
- $this->form->clear(TRUE);
- TSession::setValue(__CLASS__.'_items2', null);
- $this->onReload2( $param2 );
- }
- }
- catch (Exception $e) // in case of exception
- {
- new TMessage('error', $e->getMessage());
- TTransaction::rollback();
- }
- }
- public function onSave()
- {
- try
- {
- // open a transaction with database
- TTransaction::open('projeto');
- $data = $this->form->getData();
- $master = new TabelaVendas;
- $master->fromArray( (array) $data);
- $this->form->validate(); // form validation
- $master->store(); // save master object
- // delete details
- $old_items = TabelaVendasProdutos::where('tabela_vendas_id', '=', $master->id)->load();
- $keep_items = array();
- // get session items
- $items = TSession::getValue(__CLASS__.'_items');
- if( $items )
- {
- foreach( $items as $item )
- {
- if (substr($item['id'],0,1) == 'X' ) // new record
- {
- $detail = new TabelaVendasProdutos;
- }
- else
- {
- $detail = TabelaVendasProdutos::find($item['id']);
- }
- $detail->tabela_produtos_id = $item['tabela_produtos_id'];
- $detail->qtd_produto = $item['qtd_produto'];
- $detail->valor_produto = $item['valor_produto'];
- $detail->desconto_produto = $item['desconto_produto'];
- $detail->tabela_vendas_id = $master->id;
- $detail->store();
- $keep_items[] = $detail->id;
- }
- }
- if ($old_items)
- {
- foreach ($old_items as $old_item)
- {
- if (!in_array( $old_item->id, $keep_items))
- {
- $old_item->delete();
- }
- }
- }
- TTransaction::close(); // close the transaction
- // reload form and session items
- $this->onEdit(array('key'=>$master->id));
- //new TMessage('info', TAdiantiCoreTranslator::translate('Record saved'));
- }
- catch (Exception $e) // in case of exception
- {
- new TMessage('error', $e->getMessage());
- $this->form->setData( $this->form->getData() ); // keep form data
- TTransaction::rollback();
- }
- try
- {
- // open a transaction with database
- TTransaction::open('projeto');
- $data = $this->form->getData();
- $master = new TabelaVendas;
- $master->fromArray( (array) $data);
- $this->form->validate(); // form validation
- $master->store(); // save master object
- // delete details
- $old_items2 = TabelaVendasServicos::where('tabela_vendas_id', '=', $master->id)->load();
- $keep_items2 = array();
- // get session items
- $items2 = TSession::getValue(__CLASS__.'_items2');
- if( $items2 )
- {
- foreach( $items2 as $item2 )
- {
- if (substr($item2['id'],0,1) == 'X' ) // new record
- {
- $detail2 = new TabelaVendasServicos;
- }
- else
- {
- $detail2 = TabelaVendasServicos::find($item2['id']);
- }
- $detail2->tabela_servicos_id = $item2['tabela_servicos_id'];
- $detail2->qtd_servico = $item2['qtd_servico'];
- $detail2->valor_servico = $item2['valor_servico'];
- $detail2->desconto_servico = $item2['desconto_servico'];
- $detail2->tabela_vendas_id = $master2->id;
- $detail2->store();
- $keep_items[] = $detail2->id;
- }
- }
- if ($old_items2)
- {
- foreach ($old_items2 as $old_item2)
- {
- if (!in_array( $old_item2->id, $keep_items))
- {
- $old_item2->delete();
- }
- }
- }
- TTransaction::close(); // close the transaction
- // reload form and session items
- $this->onEdit(array('key'=>$master->id));
- new TMessage('info', TAdiantiCoreTranslator::translate('Record saved'));
- }
- catch (Exception $e) // in case of exception
- {
- new TMessage('error', $e->getMessage());
- $this->form->setData( $this->form->getData() ); // keep form data
- TTransaction::rollback();
- }
- }
- public function show()
- {
- // check if the datagrid is already loaded
- if (!$this->loaded )
- {
- $this->onReload( func_get_arg(0) );
- $this->onReload2( func_get_arg(0) );
- }
- parent::show();
- }
- }?>
Da um var_dump($master) antes do store para ver como os dados estão vindo , agora eu fiquei na duvida se está duplicando o form master ou o detail mas ambos talvez voce resolva com o php.net/manual/pt_BR/function.array-unique.php antes de mandar salvar.
Felipe, desde já agradeço sua ajuda. Achei em outro post (https://www.adianti.com.br/forum/pt/view_4734) uma sacada para poder salvar 2 detalhes, está salvando os 2 detalhes e editando normal. Mas me esbarrei em uma situação: quando edito ele não exclui o antigo, ele mantem e salva um novo. O que pode ser?
Reformulando:
Mas me esbarrei em uma situação: quando edito ele não exclui o antigo MESTRE, ele mantem o MESTRE e salva um novo MESTRE. O que pode ser?
Em algum lugar ele está dando o store com o id vazio por isso cria um novo registro.
Consegui Felipe, achei o mesmo problema em outro tópico e o Samuel me ajudou. Obrigado.