diff --git a/backend/components/AdminMenuStructure.php b/backend/components/AdminMenuStructure.php index 1a3bb1e..9fd2042 100644 --- a/backend/components/AdminMenuStructure.php +++ b/backend/components/AdminMenuStructure.php @@ -76,6 +76,7 @@ class AdminMenuStructure{ $items[] = ['label' => 'Vendégek', 'url' => ['/customer/index'] , 'target_url' => ['/customer/index' ,'/customer/view','/ticket/index-customer'] ]; $items[] = ['label' => 'Bérletkártyák', 'url' => ['/card/index'] ]; $items[] = ['label' => 'Bérletek', 'url' => ['/ticket/index' , 'TicketSearch[start]' =>$today,'TicketSearch[end]' => $tomorrow ] ]; + $items[] = ['label' => 'Statisztika', 'url' => ['/ticket/statistics' , 'TicketSearchStatisitcs[start]' =>$today,'TicketSearchStatisitcs[end]' => $tomorrow ] ]; $this->menuItems[] = ['label' => 'Bérletek/Vendégek', 'url' => $this->emptyUrl, 'items' => $items ]; @@ -98,7 +99,7 @@ class AdminMenuStructure{ // $items[] = ['label' => 'Bevétel', 'url' => ['/transfer/summary' , 'TransferSummarySearch[start]' =>$today,'TransferSummarySearch[end]' => $tomorrow ] ]; $items[] = ['label' => 'Napi bevételek', 'url' => ['/transfer/list', 'TransferListSearch[start]' =>$todayDatetime,'TransferListSearch[end]' => $tomorrowDatetime ] ]; $items[] = ['label' => 'Kassza müveletek', 'url' => ['/account-state/index'] ]; - $items[] = ['label' => 'Zárások', 'url' => ['/collection/index' , 'CollectionSearch[start]' =>$todayDatetime,'CollectionSearch[end]' => $tomorrowDatetime ] ]; + //$items[] = ['label' => 'Zárások', 'url' => ['/collection/index' , 'CollectionSearch[start]' =>$todayDatetime,'CollectionSearch[end]' => $tomorrowDatetime ] ]; $this->menuItems[] = ['label' => 'Pénzügy', 'url' => $this->emptyUrl, 'items' => $items ]; diff --git a/backend/controllers/TicketController.php b/backend/controllers/TicketController.php index 68793a6..8adc0e6 100644 --- a/backend/controllers/TicketController.php +++ b/backend/controllers/TicketController.php @@ -14,173 +14,227 @@ use common\models\Account; use common\models\User; use common\models\Customer; use common\models\Card; +use backend\models\TicketSearchStatisitcs; /** * TicketController implements the CRUD actions for Ticket model. */ -class TicketController extends \backend\controllers\BackendController -{ - - - public function behaviors() - { - return [ - 'access' => [ - 'class' => \yii\filters\AccessControl::className(), - 'rules' => [ - // allow authenticated users - [ - 'actions' => ['create','index','view','update','index-customer'], - 'allow' => true, - 'roles' => ['admin','employee','reception'], - ], +class TicketController extends \backend\controllers\BackendController { + public function behaviors() { + return [ + 'access' => [ + 'class' => \yii\filters\AccessControl::className (), + 'rules' => [ + // allow authenticated users + [ + 'actions' => [ + 'create', + 'index', + 'view', + 'update', + 'index-customer', + 'statistics' + ], + 'allow' => true, + 'roles' => [ + 'admin', + 'employee', + 'reception' + ] + ] + ] // everything else is denied - ], - ], + + ] ]; } - /** - * Lists all Ticket models. - * @return mixed - */ - public function actionIndex() - { - $searchModel = new TicketSearch(); - $dataProvider = $searchModel->search(Yii::$app->request->queryParams); - $searchModel->searchTotals(); - - $searchModel->users = User::read(); - $searchModel->accounts = Account::read(); - $searchModel->ticketTypes = TicketType::read(); - - - - return $this->render('index', [ - 'searchModel' => $searchModel, - 'dataProvider' => $dataProvider, - ]); - } - - - /** - * Lists all Ticket models. - * @return mixed - */ - public function actionIndexCustomer($id) - { - - $customer = Customer::findOne($id); - $card = Card::findOne($id); - - - if ( $customer == null ){ - throw new NotFoundHttpException('The requested page does not exist.'); - } - - $searchModel = new TicketSearch(); - $searchModel->id_card = $customer->id_customer_card; - $dataProvider = $searchModel->search(Yii::$app->request->queryParams); - $searchModel->searchTotals(); - - $searchModel->users = User::read(); - $searchModel->accounts = Account::read(); - $searchModel->ticketTypes = TicketType::read(); - - - - return $this->render('index_customer', [ - 'searchModel' => $searchModel, - 'dataProvider' => $dataProvider, - 'customer' => $customer, - 'card' => $card - ]); - } - - - /** - * Displays a single Ticket model. - * @param integer $id - * @return mixed - */ - public function actionView($id) - { - return $this->render('view', [ - 'model' => $this->findModel($id), - ]); - } - - /** - * Creates a new Ticket model. - * If creation is successful, the browser will be redirected to the 'view' page. - * @return mixed - */ - public function actionCreate() - { - $model = new Ticket(); - - $discounts = Discount::read(); - $ticketTypes = TicketType::read(); - $accounts = Account::readAccounts(); - - - if ($model->load(Yii::$app->request->post()) && $model->save()) { - return $this->redirect(['view', 'id' => $model->id_ticket]); - } else { - return $this->render('create', [ - 'model' => $model, - 'discounts' => $discounts, - 'ticketTypes' => $ticketTypes, - 'accounts' => $accounts, - ]); - } - } - - /** - * Updates an existing Ticket model. - * If update is successful, the browser will be redirected to the 'view' page. - * @param integer $id - * @return mixed - */ - public function actionUpdate($id) - { - $model = $this->findModel($id); - - if ($model->load(Yii::$app->request->post()) && $model->save()) { - return $this->redirect(['view', 'id' => $model->id_ticket]); - } else { - return $this->render('update', [ - 'model' => $model, - ]); - } - } - - /** - * Deletes an existing Ticket model. - * If deletion is successful, the browser will be redirected to the 'index' page. - * @param integer $id - * @return mixed - */ - public function actionDelete($id) - { - $this->findModel($id)->delete(); - - return $this->redirect(['index']); - } - - /** - * Finds the Ticket model based on its primary key value. - * If the model is not found, a 404 HTTP exception will be thrown. - * @param integer $id - * @return Ticket the loaded model - * @throws NotFoundHttpException if the model cannot be found - */ - protected function findModel($id) - { - if (($model = Ticket::findOne($id)) !== null) { - return $model; - } else { - throw new NotFoundHttpException('The requested page does not exist.'); - } - } + /** + * Lists all Ticket models. + * + * @return mixed + */ + public function actionIndex() { + $searchModel = new TicketSearch (); + $dataProvider = $searchModel->search ( Yii::$app->request->queryParams ); + $searchModel->searchTotals (); + + $searchModel->users = User::read (); + $searchModel->accounts = Account::read (); + $searchModel->ticketTypes = TicketType::read (); + + return $this->render ( 'index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider + ] ); + } + + /** + * Lists all Ticket models. + * + * @return mixed + */ + public function actionStatistics() { + $searchModel = new TicketSearchStatisitcs(); + $searchModel->search ( Yii::$app->request->queryParams ); + $searchModel->searchTotals (); + + $searchModel->users = User::read (); + $searchModel->accounts = Account::read (); + $searchModel->ticketTypes = TicketType::read (); + + if ($searchModel->output == 'pdf') { + $user = User::findOne ( \Yii::$app->user->id ); + $mpdf = new \mPDF ( 'utf-8', 'A4-L' ); + $fn = ""; + $ov = '_total_content_pdf'; + $dt = "_letrehozva_" . date ( "Ymd_His" ) . "_" . $user->username; + $interval = ""; + $account = ""; + $currentUser = ""; + $fn = $fn . $interval . $dt . $account . $currentUser . ".pdf"; + + $mpdf->useSubstitutions = false; + $mpdf->simpleTables = true; + $mpdf->SetHeader ( \Yii::$app->params ["company_name"] . " - Létrehozva: " . $user->username . ", " . \Yii::$app->formatter->asDatetime ( time () ) ); + $mpdf->setFooter ( '{PAGENO} / {nb}' ); + + $stylesheet = file_get_contents ( \Yii::getAlias ( '@vendor' . '/bower/bootstrap/dist/css/bootstrap.css' ) ); // external css + $mpdf->WriteHTML ( $stylesheet, 1 ); + + $mpdf->WriteHTML ( $this->renderPartial ( 'statistics_pdf', [ + 'searchModel' => $searchModel + ] ) ); + $mpdf->Output ( $fn, 'D' ); + exit (); + } else { + + return $this->render ( 'statistics', [ + 'searchModel' => $searchModel + ] ); + } + } + + /** + * Lists all Ticket models. + * + * @return mixed + */ + public function actionIndexCustomer($id) { + $customer = Customer::findOne ( $id ); + $card = Card::findOne ( $id ); + + if ($customer == null) { + throw new NotFoundHttpException ( 'The requested page does not exist.' ); + } + + $searchModel = new TicketSearch (); + $searchModel->id_card = $customer->id_customer_card; + $dataProvider = $searchModel->search ( Yii::$app->request->queryParams ); + $searchModel->searchTotals (); + + $searchModel->users = User::read (); + $searchModel->accounts = Account::read (); + $searchModel->ticketTypes = TicketType::read (); + + return $this->render ( 'index_customer', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + 'customer' => $customer, + 'card' => $card + ] ); + } + + /** + * Displays a single Ticket model. + * + * @param integer $id + * @return mixed + */ + public function actionView($id) { + return $this->render ( 'view', [ + 'model' => $this->findModel ( $id ) + ] ); + } + + /** + * Creates a new Ticket model. + * If creation is successful, the browser will be redirected to the 'view' page. + * + * @return mixed + */ + public function actionCreate() { + $model = new Ticket (); + + $discounts = Discount::read (); + $ticketTypes = TicketType::read (); + $accounts = Account::readAccounts (); + + if ($model->load ( Yii::$app->request->post () ) && $model->save ()) { + return $this->redirect ( [ + 'view', + 'id' => $model->id_ticket + ] ); + } else { + return $this->render ( 'create', [ + 'model' => $model, + 'discounts' => $discounts, + 'ticketTypes' => $ticketTypes, + 'accounts' => $accounts + ] ); + } + } + + /** + * Updates an existing Ticket model. + * If update is successful, the browser will be redirected to the 'view' page. + * + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) { + $model = $this->findModel ( $id ); + + if ($model->load ( Yii::$app->request->post () ) && $model->save ()) { + return $this->redirect ( [ + 'view', + 'id' => $model->id_ticket + ] ); + } else { + return $this->render ( 'update', [ + 'model' => $model + ] ); + } + } + + /** + * Deletes an existing Ticket model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * + * @param integer $id + * @return mixed + */ + public function actionDelete($id) { + $this->findModel ( $id )->delete (); + + return $this->redirect ( [ + 'index' + ] ); + } + + /** + * Finds the Ticket model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * + * @param integer $id + * @return Ticket the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) { + if (($model = Ticket::findOne ( $id )) !== null) { + return $model; + } else { + throw new NotFoundHttpException ( 'The requested page does not exist.' ); + } + } } diff --git a/backend/models/TicketSearchStatisitcs.php b/backend/models/TicketSearchStatisitcs.php new file mode 100644 index 0000000..c8ccbd7 --- /dev/null +++ b/backend/models/TicketSearchStatisitcs.php @@ -0,0 +1,162 @@ + 'timestampStart' ,'timestampAttributeFormat' => 'yyyy-MM-dd' ], + [[ 'end' , ], 'date' , 'timestampAttribute' => 'timestampEnd' ,'timestampAttributeFormat' => 'yyyy-MM-dd' ], + [['valid_in_interval','created_in_interval','expire_in_interval'],'boolean'] , + + ]; + } + + /** + * @inheritdoc + */ + public function scenarios() + { + // bypass scenarios() implementation in the parent class + return Model::scenarios(); + } + + public function attributeLabels(){ + return ArrayHelper::merge(parent::attributeLabels(), [ + 'start' => Yii::t('backend/ticket','Start of interval'), + 'end' => Yii::t('backend/ticket','End of interval'), + 'valid_in_interval' => Yii::t('backend/ticket','Valid in interval'), + 'created_in_interval' => Yii::t('backend/ticket','Created in interval'), + 'expire_in_interval' => Yii::t('backend/ticket','Expire in interval'), + ]); + } + + public function afterValidate(){ + + if ( !isset($this->timestampStart)) { + $this->timestampStart ='1900-01-01'; + } + + if ( !isset($this->timestampEnd)) { + $this->timestampEnd ='3000-01-01'; + } + + } + + /** + * Creates data provider instance with search query applied + * + * @param array $params + * + * @return ActiveDataProvider + */ + public function search($params) + { + $this->load($params); + $this->validate(); + + + } + + + + public function searchTotals(){ + $query = Ticket::mkStatisticQuery($this->timestampStart, $this->timestampEnd,$this->id_card); + $this->statistics = $query->all(); + + $this->statisticsTotal =[ + 'valid' => 0, + 'created' => 0, + 'created_at_money' => 0, + 'expired' => 0, + ]; + + $this->statisticsTotal['valid'] = array_sum(array_column($this->statistics, 'valid')); + $this->statisticsTotal['created'] = array_sum(array_column($this->statistics, 'created')); + $this->statisticsTotal['created_money'] = array_sum(array_column($this->statistics, 'created_money')); + $this->statisticsTotal['expired'] = array_sum(array_column($this->statistics, 'expired')); + } + + + public static function mkSearchCondition( $timestampStart, $timestampEnd, $id_user,$id_ticket_tpye,$id_account,$valid_in_interval ,$expire_in_interval,$created_in_interval ){ + $query = Ticket::find(); + + Helper::queryAccountConstraint($query, 'ticket.id_account'); + + $query->with('ticketType' ); + $query->with('user'); + $query->with('customer'); + + $query->andFilterWhere([ + 'id_user' => $id_user, + 'id_ticket_type' => $id_ticket_type, + 'id_account' => $id_account, + ]); + + $all = (!($valid_in_interval) && !($expire_in_interval) && !($created_in_interval) ) + || + ($valid_in_interval == true && $expire_in_interval == true && $created_in_interval); + + $dateConditions = []; + $start = $timestampStart; + $end = $timestampEnd; + + if( $all || $created_in_interval ){ + $dateConditions[] = Helper::queryInIntervalRule('ticket.created_at', $start, $end); + } + + if ( $all || $valid_in_interval ){ + $dateConditions[] = Helper::queryValidRule('ticket.start', 'ticket.end', $start, $end); + } + + if ( $all || $expire_in_interval ){ + $dateConditions[] = Helper::queryExpireRule('ticket.start', 'ticket.end', $start, $end); + } + + if ( count($dateConditions) == 1 ){ + $query->andWhere($dateConditions[0]); + }else if ( count($dateConditions) > 1 ){ + $cond = ['or']; + foreach ($dateConditions as $c){ + $cond[] = $c; + } + $query->andWhere($cond); + } + } + +} diff --git a/backend/models/TransferSearch.php b/backend/models/TransferSearch.php index 671ac5b..7c75095 100644 --- a/backend/models/TransferSearch.php +++ b/backend/models/TransferSearch.php @@ -87,7 +87,7 @@ class TransferSearch extends Transfer ]); - $query->addSelect( ['*' ]); +// $query->addSelect( ['*' ]); $this->load($params); @@ -103,6 +103,8 @@ class TransferSearch extends Transfer 'transfer.id_user' => $this->id_user, ]); + $query->andFilterWhere(['in' ,'transfer.type', $this->types]); + $created_condition = ['and',[ '>=', 'transfer.created_at', $this->timestampStart ] ,[ '<', 'transfer.created_at', $this->timestampEnd ] ]; $paid_condition = ['and',[ '>=', 'transfer.paid_at', $this->timestampStart ] ,[ '<', 'transfer.paid_at', $this->timestampEnd ] ]; diff --git a/backend/views/ticket/_search_statistics.php b/backend/views/ticket/_search_statistics.php new file mode 100644 index 0000000..791f2d6 --- /dev/null +++ b/backend/views/ticket/_search_statistics.php @@ -0,0 +1,65 @@ + + + 'Mind'] + ArrayHelper::map($model->ticketTypes, 'id_ticket_type', 'name'); +$accountOptions = ['' => 'Mind'] + ArrayHelper::map($model->accounts, 'id_account', 'name'); +$userOptions = ['' => 'Mind'] + ArrayHelper::map($model->users, 'id', 'username'); + +?> + +
Bérlet statisztika a kiválasztott időszakra
+ + output) ){ + + $pdfUrl = Url::current([ Html::getInputName($searchModel, 'output') => 'pdf']); + echo Html::a("PDF letöltése", $pdfUrl,['class' => 'btn btn-primary btn-all' ]); + } + + +?> + new ArrayDataProvider([ + 'allModels' => $searchModel->statistics, + 'sort' => false, + 'pagination' => false, + ]), + 'showFooter'=>TRUE, + 'footerRowOptions'=>['style'=>'font-weight:bold; '], + 'columns' =>[ + [ + 'attribute' => 'name', + 'label' => 'Bérlet', + 'footer' => 'Összesen' + ], + [ + 'attribute' => 'created', + 'label' => 'Kiadva (Db)', + 'footer' => $searchModel->statisticsTotal['created'] + ], + [ + 'attribute' => 'created_money', + 'label' => 'Kiadott érték (Ft)', + 'footer' => $searchModel->statisticsTotal['created_money'] + ], + [ + 'attribute' => 'valid', + 'label' => 'Érvényes (Db)', + 'footer' => $searchModel->statisticsTotal['valid'] + + ], + [ + 'attribute' => 'expired', + 'label' => 'Lejár az adott időszakban (Db)', + 'footer' => $searchModel->statisticsTotal['expired'] + ] + + ] + ]); + + ?> +