Problema trabalhando com datas


$model->veiculo0->save(false)

Nada amigo, mesmo assim não muda o Status. Olha tenho em meu model requisicao algumas function que crei que uso no afterSave() como no exemplo abaixo:




    public static function UpdateVeiculodisponivel() {

        $sql = "UPDATE veiculo SET ve_status = 'DISPONIVEL' WHERE ve_id = :ve_id";

        $command = Yii::app()->db->createCommand($sql);

        $command->prepare();

        $command->execute(array(':ve_id' => $this->veiculo));

        return true;

    }



Quando escolho o veiculo e insiro a requisição ela vai lá e muda o status na tabela veículo, o que acontece é que as vezes preciso alterar a requisição e quando faço isso, o status lá em veículo ainda continua INDISPONÍVEL. Gostaria de quando clicar em alterar requisição na GRIDVIEW. O sistema antes de ir ao form e trazer os dados para serem alterados, vá a VEÍCULO e altere o Status daquele veículo que está atrelado na requisição. Fazendo isto vai poder ver o veículo no DropDownList, pois o mesmo só possuem os veiculos Disponíveis.

Como faço pra usar uma function dessa acima para fazer isto, ou como posso fazer??

Agradeço a ajuda de todos.

Adriano Silva

Galera, tópicos são de graça, e não tem limites por usuários. Este aqui já mudou de assunto umas 3 vezes.

Desculpem por mudar de assunto algumas vezes, foi empolgação. Não mais acontecerá.

Finalizamos este!

Valeu Gustavo, deu certo como você falou. O que tava errado no meu foi o sinal de comparação. Muito obrigado pela ajuda amigo.

Abços,

Adriano Silva

Amigos,

Como faço pra fazer uma comparação entre datas, pois tenho um cenário com dois campos, uma data_entrada e uma data_emissao. Se por acaso o usuário digitar uma data_entrada menor que a data_emissao o sistena mostrar um erro. Já tentei mais ainda não consegui, será que alguem pode me ajudar.

OBS: Ambos os campos estão como DATE.

Sds,

Adriano

Adriano,

Você pode fazer usando o beforeValidate() no seu model.

Verifica primeiro se no seu actionCreate() existe o $model->validate() antes do $model->save().

Você pode fazer da seguinte forma, será só uma sugestão:




public function beforeValidate() {


	if(strtotime($this->data_entrada) < strtotime($this->data_emissao)){

		$this->addError('data_entrada', 'Data de entrada não pode ser menor que a Data de Emissão');

	}

	

	return parent::beforeValidate();

}



Newerton,

No actionCreate() da minha aplicação não existe. E agora como posso fazer? Deixei de mensionar que criei um cenário START, ou seja, essa data_emissão já estará no banco, seria como um update. Essa data_entrada será calculada com uma data que já estará no banco. Mesmo assim dá pra fazer desta forma?

Sds,

Adriano Silva

Dá sim!

Vai no seu actionCreate() e deixa dessa forma:

ANTES




...

if($model->save()){

...

}

...



DEPOIS




...

if($model->validate() && $model->save()){

...

}

...



Newerton,

No CREATE deu tudo certo, agora em outra aplicação minha que tenho outros cenários não dá. Coloquei no models assim:




    public function beforeValidate() {

        if ($this->isNewRecord) {

            if (!$this->hasErrors('req_saidaprev')) {

                if (CDateTimeParser::parse($this->req_saidaprev, Yii::app()->locale->dateFormat) < strtotime('now - 1day')) {

                    $this->addError('req_saidaprev', 'A data não pode ser inferior a data atual.');

                }

            }

        } elseif ($this->scenario == 'update') {

            if (!$this->hasErrors('req_saidaprev')) {

                if (CDateTimeParser::parse($this->req_saidaprev, Yii::app()->locale->dateFormat) < strtotime('now - 1day')) {

                    $this->addError('req_saidaprev', 'A data não pode ser inferior a data atual.');

                }

            }

        } elseif ($this->scenario == 'start') {

            if (!$this->hasErrors('ate_datasaida')) {

                if (strtotime($this->ate_datasaida) < strtotime($this->req_saidaprev)) {

                    $this->addError('ate_datasaida', 'A data de saida não pode ser menor da data prevista da requisição.');

                }

            } if (($this->ate_kmsaida == '' ) || (($this->ate_kmsaida) < ($this->veiculo0->kmatual))) {

                $this->addError('ate_kmsaida', 'O Hodômetro Saída não pode ser menor que Hodômetro ATUAL do veículo.');

            }

        } elseif ($this->scenario == 'finalize') {

            if (($this->ate_kmfinal <= $this->ate_kmsaida) || ($this->ate_kmfinal == '')) {

                $this->addError('ate_kmfinal', 'O Nº Hodômetro Saída não pode ser menor que Nº Hodômetro Final.');

            }

            if (!$this->hasErrors('ate_datafinal')) {

                if (strtotime($this->ate_datafinal) < strtotime($this->ate_datasaida)) {

                    $this->addError('ate_datafinal', 'A data de final não pode ser menor que a data de inicial do atendimento.');

                }

            }

        }

        return parent::beforeValidate();

    }



E no CONTROLLER assim:




    public function actionCreate() {

        $model = new requisicao;


        // Uncomment the following line if AJAX validation is needed

        //$this->performAjaxValidation($model);


        if (isset($_POST['requisicao'])) {

            $model->attributes = $_POST['requisicao'];

            if ($model->validate() && $model->save())

                $this->redirect(array('view', 'id' => $model->req_id));

        }


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

            'model' => $model,

        ));

    }


    public function actionStart() {

        $model = $this->loadModel();

        if ($model->req_status == requisicao::CATEGORIA_EMANDAMENTO) {

            throw new CHttpException(412, 'O Atendimento da Requisição já foi iniciado e não pode ser alterada.');

        } elseif ($model->req_status == requisicao::CATEGORIA_CONCLUIDO) {

            throw new CHttpException(412, 'O Atendimento da Requisição já foi Concluido e não pode ser alterada. Procure o Admininstrador do Sistema.');

        }

        if (isset($_POST['requisicao'])) {

            $model->scenario = 'start';

            $model->attributes = $_POST['requisicao'];

            if ($model->validate() && $model->start())

                $this->redirect(array('admin', 'id' => $model->req_id));

        }

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

            'model' => $model,

        ));

    }


    public function actionFinalize() {

        $model = $this->loadModel();

        if ($model->req_status == requisicao::CATEGORIA_ABERTO) {

            throw new CHttpException(412, 'O Atendimento da Requisição deve primeiro ser iniciado.');

        } elseif ($model->req_status == requisicao::CATEGORIA_CONCLUIDO) {

            throw new CHttpException(412, 'O Atendimento da Requisição já foi Concluido e não pode ser alterada. Procure o Admininstrador do Sistema.');

        }

        if (isset($_POST['requisicao'])) {

            $model->scenario = 'finalize';

            $model->attributes = $_POST['requisicao'];

            if ($model->validate() && $model->finalize())

                $this->redirect(array('admin', 'id' => $model->req_id));

        }

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

            'model' => $model,

        ));

    }



Mesmo fazendo assim, ele não faz a comparação entre as datas e consecutivamente deixa ser incluso no banco. Sabe me informar o que fiz de errado?

Sds,

Adriano Silva

eu faço algo como o seguinte sempre que preciso de uma regra específica de validação, que não é reusavel




class MyModel extends CActiveRecord{

  function rules(){

	return array(

  	array('data_inicio','validarData')

	);

  }

  function validarData(){

	if($this->data_inicio > $this->data_fim){

  	$this->addError('data_inicio','Data de início deve ser menor que data final');

	}

  }

}



pra regras reusáveis crio uma nova classe que extende CValidate

um detalhe, o metodo save do activerecord por padrão já faz a validação, não é necessário chamar validate depois save

o primeiro parametro do método é um boolean dizendo se deve validar ou não, que por padrão é que sim, e caso não valide ele não salva

$model->save(false) vai ignorar a validação

Grande Gustavo,

Valeu cara deu certo e ficou assim:




    public function validaInicio() {

        if (!$this->hasErrors('ate_datasaida')) {

            if (CDateTimeParser::parse($this->ate_datasaida, Yii::app()->locale->dateFormat) < CDateTimeParser::parse($this->req_saidaprev, Yii::app()->locale->dateFormat)) {

                $this->addError('ate_datasaida', 'A data saida não pode ser inferior a data prevista.');

                return false;

            }

        }

        return true;

    }


    public function rules() {

      return array(

            array('ate_datasaida', 'validaInicio', 'on' => 'start, updatestart'),

            array('ate_datafinal', 'validaFim', 'on' => 'finalize, updatfinalize'),

        );

    }



Obrigado mesmo amigo,

Adriano Silva

Gustavo,

Só por curiosidade, ainda não aconteceu comigo, se por acaso estes campos fossem DATETIME eu poderia fazer desta forma que também daria certo?

Sds,

Adriano Silva

Opa

Gostei como vc usou o CDateTimeParser junto com o componente locale

Da sim, isso serve sempre que precisar de uma validação diferente

se for fazer uma reusável, ou que precise validar "client side", por javascript, por exemplo, cnpj, cpf, cep, etc., crie um novo arquivo digamos CpfValidator que extenda CValidator e use como


function rules(){

  return array(

	array('meu_atributo','application.components.validators.CpfValidator')//use o alias correspondente ao local do arquivo 

  );

}

pra criar a classe é bem simples, abra uns 2 validators incluídos no framework e veja como foiu feito que você já pega

Amigo precisei outra validação em relação a datas, onde seria quando o usuário digitasse a ate_datasaida que fosse maior que 5 dias após a data req_saidaprev. Ele também não passasse. Só que deu problema.

Fiz assim:




            if (!$this->hasErrors('ate_datasaida')) {

                if (($this->ate_datasaida < $this->req_saidaprev) || ($this->ate_datasaida > (strtotime($this->req_saidaprev, '+5day')))) {

                    $this->addError('ate_datasaida', 'A data de saida não pode ser inferior ou 5 dias a mais que a data prevista da requisição.');

                }

            }



O que fiz de errado?

Sds,

Adriano Silva

OPS, deu certo e segue abaixo o código:




                if (($this->ate_datasaida < $this->req_saidaprev) || ($this->ate_datasaida > (strtotime($this->req_saidaprev) + strtotime('+5day')))) {

                    $this->addError('ate_datasaida', 'A data de saida não pode ser inferior ou 5 dias a mais que a data prevista da requisição.');

                }

            }



É amigos pensei que estava tudo cero, mais quando dá a virada de um mês para o outro a função não dá certo. Como posso resolver isto, alguém pode me ajudar?

Sds,

Adriano Silva

Amigos,

Estou com um problema no retorno de dados, fiz uma consulta do banco pra que me retorne na GridView a consulta. Fiz a consulta com um BETWEEN mais não me retorna nada. Estou usando dois campos de data para fazer a comparação.

Bem os códigos estão assim:

_CONTROLLER




	private function getFilter() {

    	return array(

        	'req_saidaprev' => isset($_POST['req_saidaprev']) ? CDateTimeParser::parse($_POST['req_saidaprev'], Yii::app()->locale->dateFormat) : strtotime('now - 15 day'),

        	'ate_datasaida' => isset($_POST['ate_datasaida']) ? CDateTimeParser::parse($_POST['ate_datasaida'], Yii::app()->locale->dateFormat) : strtotime('now'),

    	);

	}


	/* INÍCIO DOS RELATÓRIOS */


	/* Relatório de Requisições - SETOR */


	public function actionReqsetor() {

    	$filter = $this->getFilter();

    	$dataProvider = $this->defaultDataProviderSetor();


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

        	'dataProvider' => $dataProvider,

        	'filter' => $filter,

    	));

	}


	public function defaultDataProviderSetor() {

    	$filter = $this->getFilter();


    	$criteria = new CDbCriteria(array(

                	'distinct' => true,

                	'alias' => 'r',

                	'select' => 'r.req_saidaprev , s.set_nome as origem, count(*) as Total, SUM(r.ate_kmrodado)as ate_kmrodado',

                	'join' => 'JOIN setor s ON s.set_id = r.origem',

                	'group' => 'r.req_saidaprev, r.origem',

            	));


    	$criteria->condition = '(r.req_status = "CONCLUIDO") AND(r.req_saidaprev BETWEEN :inicio AND :fim)';

    	$criteria->params = array(':inicio' => $filter['req_saidaprev'],

        	':fim' => $filter['ate_datasaida']);


    	$dataProvider = new CActiveDataProvider('requisicao',

                    	array(

                        	'pagination' => array(

                            	'pageSize' => 30,

                        	),

                        	'criteria' => $criteria,

                    	)

    	);

    	return $dataProvider;

	}



no VIEW/__reqsetor.php




<?php $this->renderPartial('index'); ?>

<div class="demo_box">


	<h4><b>Filtro por Setor</b></h4>


	<div class="form">


    	<?php echo CHtml::beginForm(); ?>


    	<div class="row"> 	

        	<?php echo CHtml::label('', 'req_saidaprev'); ?>

        	Período de: <?php

        	$this->widget('zii.widgets.jui.CJuiDatePicker', array(

            	'name' => 'req_saidaprev',

            	'language' => 'pt-BR',

            	'value' => date('Y/m/d', $req_saidaprev),

            	'options' => array(

                	'showAnim' => 'fold', // 'show' (the default), 'slideDown', 'fadeIn', 'fold'

                	'showOn' => 'both', // 'focus', 'button', 'both'

                	'buttonText' => 'Selecionar o calendário',

                	'buttonImage' => Yii::app()->request->baseUrl . '/images/icones/calendar.png',

                	'buttonImageOnly' => true,

            	),            	

            	'htmlOptions' => array(

                	'style' => 'width:80px;vertical-align:center'

            	),

        	));

        	?>

        	a

        	<?php

        	$this->widget('zii.widgets.jui.CJuiDatePicker', array(

            	'name' => 'ate_datasaida',

            	'language' => 'pt-BR',

            	'value' => date('Y/m/d', $ate_datasaida),

            	'options' => array(

                	'showAnim' => 'fold', // 'show' (the default), 'slideDown', 'fadeIn', 'fold'

                	'showOn' => 'both', // 'focus', 'button', 'both'

                	'buttonText' => 'Selecionar o calendário',

                	'buttonImage' => Yii::app()->request->baseUrl . '/images/icones/calendar.png',

                	'buttonImageOnly' => true,

            	),

            	

            	'htmlOptions' => array(

                	'style' => 'width:80px;vertical-align:center'

            	),

        	));

        	?>

    	</div>

    	<div class="row buttons">

        	<?php echo CHtml::submitButton('Filtrar'); ?>

    	</div>


    	<?php echo CHtml::endForm(); ?>

	</div><!-- form -->

</div>



Alguém pode me informar o que estou fazendo de errado. Quando eu coloco as datas "na mão" no código, como por exemplo "BETWEEN 2011-09-26 and 2011-10-14", ele me retorna a consulta OK, mais quando parametrizo não me retorna nada.

Se possível gostaria muito da ajuda dos amigos,

Sds,

Adrian Lucas

Adrian,

Eu posso eu posso está errado, mais na query tem que ter aspa simples nas datas:




AND(r.req_saidaprev BETWEEN \':inicio\' AND \':fim\')



Uma outra coisa depois do $filter = $this->getFilter(), dá um print_r() e verifica se está indo corretamente formatada as datas.

Acho que no mais é só isso.

Amigo,

Em outra consulta em outro sistena meu, deu certo, a diferença é que no outro eu jogava as datas como INT e tratava seu retorno, e nesse eu estou jogando com DATE mesmo, então acho que é algum problema no $filter. Só não sei como resolver.

Como faço o print_r() ??

Sds,

Adrian Lucas