Ajuda: Listar Apenas Faturas Vencidas...

Amigos, preciso de mais uma ajudinha.

Estou listando todas as faturas, quero poder listar apenas as faturas já vencidas. Atualmente minha actionAdmin está assim:




public function actionAdmin()

{

	$model=new Fatura('search');

	$model->unsetAttributes();  // clear any default values

	if(isset($_GET['Fatura']))

		$model->attributes=$_GET['Fatura'];


	$this->render('admin',array(

		'model'=>$model,

	));

}



Tentei criando uma actionVencidas() que ficou mais ou menos assim:




public function actionVencidas()

{

	$dataHoje = date('Y-m-d');

	$model = Fatura::model()->findAll(array(

		'condition'=>'status=:status AND vencimento >= :date',

		'params'=>array(':status'=>'Em Aberto', ':date'=>$dataHoje),

	));


	$this->render('admin',array(

		'model'=>$model,

	));

}



… só que não deu muito certo… apresentou o erro abaixo:

Fatal error: Call to a member function search() on a non-object in %%%%%%\hiadmin\protected\views\fatura\admin.php on line 52

Alguém pode me dar uma luz? :D

Abraços!!!!

Cara, provavelmente no seu grid o dataprovider deve estar $model->search(). Você precisa criar outra função de search no model com outro nome e chamar no gridview/listview $model->searchFaturasVencidas() e nesta função definir os parametros da busca com $criteria->compare…

outra coisa importante… esse view do admin será o mesmo para os 2 modelos?

Faz o seguinte pra eu poder ajudar melhor manda o código do view, do controller e do model.

Marnei,

Na sua actionAdmin() é buscada somente a função search() que faz parte do seu Model Fatura, observa na sua actionAdmin() como é executado:


$model=new Fatura('search');

Se os dados for definitivo, digamos que, sem precisar de filtro, as alterações serão feita na function search() do model Fatura.

As faturas já vencidas, será padrão na listagem da view (admin), ou ta usando algum filtro na listagem?

Respondendo essa pergunta, chegaremos em uma solução melhor pra você.

Olá thiagovidal, obrigado pela ajuda.

Sim, no grid o dataProvider está $model->search().

Estou enviando abaixo os códigos que você pediu.

View (estou usando o bootstrap):




<?php

$this->widget('bootstrap.widgets.TbGridView', array(

	'type'=>'striped bordered condensed',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'template'=>"{items}",

	'columns'=>array(

		array('name'=>'id_fatura', 'header'=>'ID'),

		array('name'=>'descricao', 'header'=>'Descrição'),

		array('name'=>'valor', 'header'=>'Valor'),

		array('name'=>'vencimento', 'header'=>'Vencimento'),

		array('name'=>'status', 'header'=>'Status'),

		array(

			'class'=>'bootstrap.widgets.TbButtonColumn',

			'htmlOptions'=>array('style'=>'width: 50px'),

		),

	),

));

?>



Controller:




public function actionAdmin()

{

	$model=new Fatura('search');

	$model->unsetAttributes();  // clear any default values

	if(isset($_GET['Fatura']))

		$model->attributes=$_GET['Fatura'];


	$this->render('admin',array(

		'model'=>$model,

	));

}



Model:




public function search()

{

	// Warning: Please modify the following code to remove attributes that

	// should not be searched.


	$criteria=new CDbCriteria;


	$criteria->compare('id_fatura',$this->id_fatura);

	$criteria->compare('fk_cliente',$this->fk_cliente);

	$criteria->compare('fk_servico_contratado',$this->fk_servico_contratado);

	$criteria->compare('valor',$this->valor,true);

	$criteria->compare('descricao',$this->descricao,true);

	$criteria->compare('vencimento',$this->vencimento,true);

	$criteria->compare('status',$this->status,true);


	return new CActiveDataProvider($this, array(

		'criteria'=>$criteria,

	));

}



Mais uma vez, obrigado pela atenção.

Abraços!!!

Olá Newerton,

Então, eu estou querendo saber qual é a forma correta de fazer essa listagem. O "faturas vencidas" não será padrão na listagem da view (admin), a listagem padrão é a de todas as faturas cadastradas. Eu to fazendo um filtro de status "Faturas em Aberto" e "Faturas Pagas" e esse filtro eu já consegui fazer assim:




public function actionAdmin($status = null)

{

	$model=new Fatura('search');

	$model->unsetAttributes();  // clear any default values

	$model->status = $status;

	if(isset($_GET['Fatura']))

		$model->attributes=$_GET['Fatura'];


	$this->render('admin',array(

		'model'=>$model,

	));

}



Agora, não sei como fazer para listar as faturas vencidas…

Espero ter respondido sua pergunta :D

Obrigado pela atenção de sempre… Abraços!

Então… eu dei uma olhada no código e o erro é aquele que citei mesmo. Explica uma coisa que te envio a resposta correta. Como vc quer fazer isso… Tem várias maneiras:

1 - criar duas actions separadas com views diferentes com valores do grid diferentes

2 - criar um filtro tipo search na view que filtre os resultados que vc quer

3 - criar mais um metodo search e prefixar os valores dos compares

4 - criar na mesma view atribuição dinâmica de dataprovider…

Como vc prefere fazer isso?

Eu normalmente prefixo na minha função search que esta dentro do model aquilo que o usuário não poderá filtrar

e demais necessidades, depois na gridview eu crio uma pesquisa avançada com os valores que o usuário poderá filtar… vc tb pode criar um link que atualiza o ajax do grid com os parametros que vc quer…

Então cara… tem diversas formas… precisa decidir o que é melhor para você e definir… Mas com o código que vc passou no início vc não vai conseguir muita coisa.

Alias pq vc não define os valores dos labels das colunas no model dentro da função attributeLabels() ai vc terá consistência nos nomes nas forms e nas views… Eu só uso assim e sempre funciona bem… ai vc não precisa definir os headers no cgridview

Verdade, é que como eu estou aprendendo a utilizar o bootstrap eu peguei um exemplo de uso com esses headers e acabei deixando como no exemplo. Já tirei e ficou melhor mesmo :D

Eu já uso um filtro mais ou menos como você escreveu na opção 2, mas é para o status que eu já consegui fazer (não sei se é a forma mais correta):

admin.php




<?php

$this->widget('bootstrap.widgets.TbButtonGroup', array(

	'type'=>'primary',

	'buttons'=>array(

		array('label'=>'Listar Todas', 'url'=>$this->createAbsoluteUrl('/fatura/admin')),

		array('items'=>array(

			array('label'=>'Faturas em Aberto', 'url'=>$this->createAbsoluteUrl('/fatura/admin&status=Aberto')),

			array('label'=>'Faturas Pagas', 'url'=>$this->createAbsoluteUrl('/fatura/admin&status=Paga')),

		)),

	),

));

?>



Controller:




	public function actionAdmin($status = null)

	{

		$model=new Fatura('search');

		$model->unsetAttributes();  // clear any default values

		$model->status = $status;

		if(isset($_GET['Fatura']))

			$model->attributes=$_GET['Fatura'];


		$this->render('admin',array(

			'model'=>$model,

		));

	}



Não sei se para filtrar as faturas vencidas eu poderia fazer mais ou menos da mesma maneira. Acho que as melhores opções seriam a 2 ou 3 não?

Se puder escrever o código de como você faria eu agradeço :D

Obrigado pela ajuda amigão…

Marnei,

Vou postar uma solução rápida que sempre uso.

Javascript:




Yii::app()->clientScript->registerScript("admin","


$('a#filtro').live('click', function(){

    $.fn.yiiGridView.update('table-grid', {

        url:'?Filtro[tipo]=vencimento&Filtro[vencimento]=' + $('select[id=vencimento] option:selected').val()

    });

    return false;

});


");



Filtro:




<select class="input" name="vencimento" id="vencimento">

	<option value="" selected>Todos</option>

	<option value="aberto">Fatura em aberto</option>

	<option value="pagas">Fatura paga</option>

</select>


<a class="btn" id="filtro"><i class="icon-search"></i> Buscar</a>



TbGridView (Colocar ID):




$this->widget('bootstrap.widgets.TbGridView', array(

	'id' => 'table-grid',

	'type'=>'striped bordered condensed',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'template'=>"{items}",

	'columns'=>array(

			array('name'=>'id_fatura', 'header'=>'ID'),

			array('name'=>'descricao', 'header'=>'Descrição'),

			array('name'=>'valor', 'header'=>'Valor'),

			array('name'=>'vencimento', 'header'=>'Vencimento'),

			array('name'=>'status', 'header'=>'Status'),

			array(

					'class'=>'bootstrap.widgets.TbButtonColumn',

					'htmlOptions'=>array('style'=>'width: 50px'),

			),

	),

));



function search(){}:




class Fatura extends CActiveRecord {




	[...]

	

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id_fatura',$this->id_fatura);

		$criteria->compare('fk_cliente',$this->fk_cliente);

		$criteria->compare('fk_servico_contratado',$this->fk_servico_contratado);

		$criteria->compare('valor',$this->valor,true);

		$criteria->compare('descricao',$this->descricao,true);

		$criteria->compare('vencimento',$this->vencimento,true);

		$criteria->compare('status',$this->status,true);

		

		if (isset($_GET["Filtro"])) {

            if (!empty($_GET['Filtro']['tipo']) && $_GET['Filtro']['tipo'] == 'vencimento') {


                if ($_GET['Filtro']["vencimento"] == "aberto") {

				

                    $criteria->addCondition("vencimento > :vencimento");

                    $criteria->params = array(':vencimento' => date('Y-m-d'));

					

                } else if ($_GET['Filtro']["vencimento"] == "pagas") {

				

                    $criteria->addCondition("vencimento <= :vencimento");

                    $criteria->params = array(':vencimento' => date('Y-m-d'));

					

                }

				

            }

        }


		return new CActiveDataProvider($this, array(

				'criteria'=>$criteria,

		));

	}

	

}



O modo que fiz, não vai afetar o filtro padrão do framework que é usando na listagem, assim você pode usar o filtro com <select> se quizer pode colocar até um TbDatePicker no Filtro da coluna vencimento.

Newerton, é isso mesmo… deu certinho!

Mais uma vez, muito obrigado!!! :D

@Marnei que bom que conseguiu. Não sabia o grau de envolvimento que vc tinha com o framerwork ainda. Desculpe por ter aberto tanto o leque de opções assim. Não pude ver hoje para porder auxiliar. Achei a opnião do Newerton muito boa. Bacana que esta utilizando o Yii Bootstrap… É uma ótima extensão. De uma olhada nestas outras depois se quiser fazer um tune up em suas aplicações:

  • Yii Boilerplate

  • Yii Booster

  • Yii Bootstrap

  • Rights

Eu mesmo desenvoli algumas que estão no site. Procure por thiagovidal nas extensões que vc acha. Não estou podendo atualiza-las por falta de tempo… mas elas funcionam bem.

Outra coisa importante que percebi durante o tempo que trabalho com o framework é a importância de definir corretamente as relações e os valores retornados para evitar exposição de conteúdo e falhas de segurança. Não sei se esta utilizando mas se sim… verifique se o retorno dos relacionamentos não estão trazendo informações importantes como senhas de usuários para o cliente.

De qq maneira. Fico feliz que tenha conseguido! Abraço e boa sorte fera.

Qq coisa estarei a disposição.

Abc!

Thiago, muito obrigado mesmo. Sou MUITO novato no Yii, mas a cada dia que passa fico impressionado com o framework.

Vou buscar sim mais informações sobre essas extensões que você comentou… estou gostando bastante do fórum, muitos amigos experientes ajudando à nós novatos :D

Grande abraço!