Commit bfd986312e53156499a3584eee479724eeee979e
Merge remote-tracking branch 'origin/master' into Credits
Showing
4 changed files
with
265 additions
and
12 deletions
Show diff stats
controllers/StatisticsController.php
| @@ -2,15 +2,76 @@ | @@ -2,15 +2,76 @@ | ||
| 2 | 2 | ||
| 3 | namespace artweb\artbox\ecommerce\controllers; | 3 | namespace artweb\artbox\ecommerce\controllers; |
| 4 | 4 | ||
| 5 | + use artweb\artbox\ecommerce\models\Label; | ||
| 6 | + use artweb\artbox\ecommerce\models\Order; | ||
| 7 | + use yii\data\ActiveDataProvider; | ||
| 8 | + use yii\helpers\ArrayHelper; | ||
| 9 | + use yii\helpers\VarDumper; | ||
| 5 | use yii\web\Controller; | 10 | use yii\web\Controller; |
| 6 | 11 | ||
| 7 | - /** | ||
| 8 | - * BrandController implements the CRUD actions for Brand model. | ||
| 9 | - */ | ||
| 10 | class StatisticsController extends Controller | 12 | class StatisticsController extends Controller |
| 11 | { | 13 | { |
| 12 | - public function actionIndex() | 14 | + public function actionIndex($date_range = NULL, $label = NULL) |
| 13 | { | 15 | { |
| 14 | - return $this->render('index'); | 16 | + /** |
| 17 | + * Get a dates range | ||
| 18 | + */ | ||
| 19 | + if (!empty($date_range)) { | ||
| 20 | + $arr = []; | ||
| 21 | + preg_match('@(.*)\s:\s(.*)@', $date_range, $arr); | ||
| 22 | + $dateFilter = [ | ||
| 23 | + 'between', | ||
| 24 | + 'created_at', | ||
| 25 | + strtotime($arr[1]), | ||
| 26 | + strtotime($arr[2]), | ||
| 27 | + ]; | ||
| 28 | + } else { | ||
| 29 | + $dateFilter = []; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + if (!empty($label)) { | ||
| 33 | + $labelFilter = ['label' => $label]; | ||
| 34 | + } else { | ||
| 35 | + $labelFilter = []; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * Get labels | ||
| 40 | + */ | ||
| 41 | + $labels = Label::find() | ||
| 42 | + ->with('lang') | ||
| 43 | + ->all(); | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * Generate statistics | ||
| 47 | + */ | ||
| 48 | + $labelStatistics = ArrayHelper::map( | ||
| 49 | + $labels, | ||
| 50 | + function($model) { | ||
| 51 | + /** | ||
| 52 | + * @var Label $model | ||
| 53 | + */ | ||
| 54 | + return $model->lang->title; | ||
| 55 | + }, | ||
| 56 | + function($model) use ($dateFilter) { | ||
| 57 | + /** | ||
| 58 | + * @var Label $model | ||
| 59 | + */ | ||
| 60 | + return $model->getStatistics($dateFilter);} | ||
| 61 | + ); | ||
| 62 | + | ||
| 63 | + $dataProvider = new ActiveDataProvider([ | ||
| 64 | + 'query' => Order::find()->filterWhere($dateFilter)->andFilterWhere($labelFilter), | ||
| 65 | + ]); | ||
| 66 | + | ||
| 67 | + return $this->render( | ||
| 68 | + 'index', | ||
| 69 | + [ | ||
| 70 | + 'labels' => $labels, | ||
| 71 | + 'labelStatistics' => $labelStatistics, | ||
| 72 | + 'rejectionStatistics' => Order::getRejectionStatistics($dateFilter), | ||
| 73 | + 'dataProvider' => $dataProvider, | ||
| 74 | + ] | ||
| 75 | + ); | ||
| 15 | } | 76 | } |
| 16 | } | 77 | } |
models/Label.php
| @@ -5,6 +5,8 @@ | @@ -5,6 +5,8 @@ | ||
| 5 | use artweb\artbox\language\behaviors\LanguageBehavior; | 5 | use artweb\artbox\language\behaviors\LanguageBehavior; |
| 6 | use yii\db\ActiveQuery; | 6 | use yii\db\ActiveQuery; |
| 7 | use yii\db\ActiveRecord; | 7 | use yii\db\ActiveRecord; |
| 8 | + use yii\db\Query; | ||
| 9 | + use yii\helpers\VarDumper; | ||
| 8 | use yii\web\Request; | 10 | use yii\web\Request; |
| 9 | 11 | ||
| 10 | /** | 12 | /** |
| @@ -62,4 +64,41 @@ | @@ -62,4 +64,41 @@ | ||
| 62 | ], | 64 | ], |
| 63 | ]; | 65 | ]; |
| 64 | } | 66 | } |
| 67 | + | ||
| 68 | + public function getStatistics(array $where = []) | ||
| 69 | + { | ||
| 70 | + $query = ( new Query() )->select( | ||
| 71 | + [ | ||
| 72 | + 'sum' => 'SUM(total)', | ||
| 73 | + 'count' => 'COUNT(*)', | ||
| 74 | + 'unique' => ( new Query() )->select('COUNT(*)') | ||
| 75 | + ->from('order') | ||
| 76 | + ->leftJoin( | ||
| 77 | + 'order_product', | ||
| 78 | + '"order"."id"="order_product"."order_id"' | ||
| 79 | + ) | ||
| 80 | + ->where([ 'order.label' => $this->id ]) | ||
| 81 | + ->andFilterWhere( | ||
| 82 | + $where | ||
| 83 | + ), | ||
| 84 | + 'products' => ( new Query() )->select('SUM(count)') | ||
| 85 | + ->from('order') | ||
| 86 | + ->leftJoin( | ||
| 87 | + 'order_product', | ||
| 88 | + '"order"."id"="order_product"."order_id"' | ||
| 89 | + ) | ||
| 90 | + ->where([ 'order.label' => $this->id ]) | ||
| 91 | + ->andFilterWhere( | ||
| 92 | + $where | ||
| 93 | + ), | ||
| 94 | + ] | ||
| 95 | + ) | ||
| 96 | + ->from('order') | ||
| 97 | + ->where([ 'label' => $this->id ]) | ||
| 98 | + ->andFilterWhere( | ||
| 99 | + $where | ||
| 100 | + ); | ||
| 101 | + | ||
| 102 | + return $query->one(); | ||
| 103 | + } | ||
| 65 | } | 104 | } |
models/Order.php
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | use Yii; | 7 | use Yii; |
| 8 | use yii\behaviors\TimestampBehavior; | 8 | use yii\behaviors\TimestampBehavior; |
| 9 | use yii\db\ActiveRecord; | 9 | use yii\db\ActiveRecord; |
| 10 | + use yii\db\Query; | ||
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | * Class Order | 13 | * Class Order |
| @@ -93,6 +94,32 @@ | @@ -93,6 +94,32 @@ | ||
| 93 | { | 94 | { |
| 94 | return 'order'; | 95 | return 'order'; |
| 95 | } | 96 | } |
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * @param array $where | ||
| 100 | + * | ||
| 101 | + * @return array | ||
| 102 | + */ | ||
| 103 | + public static function getRejectionStatistics(array $where = []) | ||
| 104 | + { | ||
| 105 | + $result = []; | ||
| 106 | + foreach (self::REASONS as $id => $reason) { | ||
| 107 | + $result[ $reason ] = ( new Query() )->select( | ||
| 108 | + [ | ||
| 109 | + 'sum' => 'SUM(total)', | ||
| 110 | + 'count' => 'COUNT(*)', | ||
| 111 | + ] | ||
| 112 | + ) | ||
| 113 | + ->from(self::tableName()) | ||
| 114 | + ->where( | ||
| 115 | + [ | ||
| 116 | + 'reason' => $id, | ||
| 117 | + ] | ||
| 118 | + )->andFilterWhere($where)->one(); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + return $result; | ||
| 122 | + } | ||
| 96 | 123 | ||
| 97 | public function behaviors() | 124 | public function behaviors() |
| 98 | { | 125 | { |
| @@ -203,7 +230,7 @@ | @@ -203,7 +230,7 @@ | ||
| 203 | public function afterFind() | 230 | public function afterFind() |
| 204 | { | 231 | { |
| 205 | parent::afterFind(); | 232 | parent::afterFind(); |
| 206 | - $this->deadline = !empty( $this->deadline ) ? date('d.m.Y', $this->deadline) : ''; | 233 | + $this->deadline = !empty($this->deadline) ? date('d.m.Y', $this->deadline) : ''; |
| 207 | 234 | ||
| 208 | } | 235 | } |
| 209 | 236 | ||
| @@ -220,7 +247,7 @@ | @@ -220,7 +247,7 @@ | ||
| 220 | 247 | ||
| 221 | protected function convertDate() | 248 | protected function convertDate() |
| 222 | { | 249 | { |
| 223 | - if (!empty( $this->deadline )) { | 250 | + if (!empty($this->deadline)) { |
| 224 | $date = new \DateTime(); | 251 | $date = new \DateTime(); |
| 225 | $date->setTimestamp(strtotime($this->deadline)); | 252 | $date->setTimestamp(strtotime($this->deadline)); |
| 226 | $date->format("d.m.Y"); | 253 | $date->format("d.m.Y"); |
| @@ -311,8 +338,8 @@ | @@ -311,8 +338,8 @@ | ||
| 311 | */ | 338 | */ |
| 312 | public function getDeliveryString() | 339 | public function getDeliveryString() |
| 313 | { | 340 | { |
| 314 | - if (!empty( $this->orderDelivery )) { | ||
| 315 | - if (!empty( $this->orderDelivery->parent )) { | 341 | + if (!empty($this->orderDelivery)) { |
| 342 | + if (!empty($this->orderDelivery->parent)) { | ||
| 316 | return $this->orderDelivery->parent->lang->title . ': ' . $this->orderDelivery->lang->title; | 343 | return $this->orderDelivery->parent->lang->title . ': ' . $this->orderDelivery->lang->title; |
| 317 | } else { | 344 | } else { |
| 318 | return $this->orderDelivery->lang->title; | 345 | return $this->orderDelivery->lang->title; |
| @@ -330,7 +357,7 @@ | @@ -330,7 +357,7 @@ | ||
| 330 | */ | 357 | */ |
| 331 | public function getWasted() | 358 | public function getWasted() |
| 332 | { | 359 | { |
| 333 | - if (empty( $this->deadline )) { | 360 | + if (empty($this->deadline)) { |
| 334 | return false; | 361 | return false; |
| 335 | } else { | 362 | } else { |
| 336 | return time() > strtotime($this->deadline); | 363 | return time() > strtotime($this->deadline); |
views/statistics/index.php
| 1 | <?php | 1 | <?php |
| 2 | + use artweb\artbox\ecommerce\models\Label; | ||
| 3 | + use kartik\daterange\DateRangePicker; | ||
| 4 | + use kartik\grid\GridView; | ||
| 5 | + use kartik\select2\Select2; | ||
| 6 | + use yii\data\ActiveDataProvider; | ||
| 7 | + use yii\helpers\ArrayHelper; | ||
| 8 | + use yii\helpers\Html; | ||
| 2 | use yii\web\View; | 9 | use yii\web\View; |
| 3 | 10 | ||
| 4 | /** | 11 | /** |
| 5 | - * @var View $this | 12 | + * @var View $this |
| 13 | + * @var Label[] $labels | ||
| 14 | + * @var array $labelStatistics | ||
| 15 | + * @var array $rejectionStatistics | ||
| 16 | + * @var ActiveDataProvider $dataProvider | ||
| 6 | */ | 17 | */ |
| 7 | 18 | ||
| 8 | ?> | 19 | ?> |
| @@ -15,6 +26,121 @@ | @@ -15,6 +26,121 @@ | ||
| 15 | </div><!-- /.box-tools --> | 26 | </div><!-- /.box-tools --> |
| 16 | </div><!-- /.box-header --> | 27 | </div><!-- /.box-header --> |
| 17 | <div class="box-body"> | 28 | <div class="box-body"> |
| 18 | - The body of the box | 29 | + <?= Html::beginForm( |
| 30 | + [ '/ecommerce/statistics' ], | ||
| 31 | + 'get' | ||
| 32 | + ) ?> | ||
| 33 | + <div class="row"> | ||
| 34 | + <div class="col-md-4"> | ||
| 35 | + <?= DateRangePicker::widget( | ||
| 36 | + [ | ||
| 37 | + 'name' => 'date_range', | ||
| 38 | + 'pluginOptions' => [ | ||
| 39 | + 'locale' => [ | ||
| 40 | + 'format' => 'DD-MM-Y', | ||
| 41 | + 'separator' => ' : ', | ||
| 42 | + ], | ||
| 43 | + ], | ||
| 44 | + ] | ||
| 45 | + ) ?> | ||
| 46 | + </div> | ||
| 47 | + <div class="col-md-6"> | ||
| 48 | + <?= Select2::widget( | ||
| 49 | + [ | ||
| 50 | + 'name' => 'label', | ||
| 51 | + 'data' => ArrayHelper::map( | ||
| 52 | + $labels, | ||
| 53 | + function($model) { | ||
| 54 | + return $model->id; | ||
| 55 | + }, | ||
| 56 | + function($model) { | ||
| 57 | + return $model->lang->title; | ||
| 58 | + } | ||
| 59 | + ), | ||
| 60 | + 'options' => [ | ||
| 61 | + 'placeholder' => 'Все', | ||
| 62 | + ], | ||
| 63 | + ] | ||
| 64 | + ) ?> | ||
| 65 | + </div> | ||
| 66 | + <div class="col-md-2"> | ||
| 67 | + <?= Html::submitButton( | ||
| 68 | + 'Go', | ||
| 69 | + [ | ||
| 70 | + 'class' => 'btn btn-success', | ||
| 71 | + ] | ||
| 72 | + ) ?> | ||
| 73 | + </div> | ||
| 74 | + </div> | ||
| 75 | + <?= Html::endForm() ?> | ||
| 19 | </div><!-- /.box-body --> | 76 | </div><!-- /.box-body --> |
| 20 | </div><!-- /.box --> | 77 | </div><!-- /.box --> |
| 78 | + | ||
| 79 | +<div class="box box-default"> | ||
| 80 | + <div class="box-header with-border"> | ||
| 81 | + <h3 class="box-title">Метки, статистика за </h3> | ||
| 82 | + <div class="box-tools pull-right"> | ||
| 83 | + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button> | ||
| 84 | + </div><!-- /.box-tools --> | ||
| 85 | + </div><!-- /.box-header --> | ||
| 86 | + <div class="box-body table-responsive no-padding"> | ||
| 87 | + <table class="table table-hover"> | ||
| 88 | + <tr> | ||
| 89 | + <td><b>Метка</b></td> | ||
| 90 | + <td><b>Заказов, шт.</b></td> | ||
| 91 | + <td><b>На сумму, грн.</b></td> | ||
| 92 | + <td><b>Заказано товаров, шт.</b></td> | ||
| 93 | + <td><b>Уникальных товаров, шт.</b></td> | ||
| 94 | + </tr> | ||
| 95 | + <?php | ||
| 96 | + foreach ($labelStatistics as $name => $statistic) { | ||
| 97 | + ?> | ||
| 98 | + <tr> | ||
| 99 | + <td><?= $name ?></td> | ||
| 100 | + <td><?= $statistic[ 'count' ] ?></td> | ||
| 101 | + <td><?= $statistic[ 'sum' ] ?></td> | ||
| 102 | + <td><?= $statistic[ 'products' ] ?></td> | ||
| 103 | + <td><?= $statistic[ 'unique' ] ?></td> | ||
| 104 | + </tr> | ||
| 105 | + <?php } ?> | ||
| 106 | + </table> | ||
| 107 | + </div><!-- /.box-body --> | ||
| 108 | +</div><!-- /.box --> | ||
| 109 | + | ||
| 110 | +<div class="box box-default"> | ||
| 111 | + <div class="box-header with-border"> | ||
| 112 | + <h3 class="box-title">Метки, статистика за </h3> | ||
| 113 | + <div class="box-tools pull-right"> | ||
| 114 | + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button> | ||
| 115 | + </div><!-- /.box-tools --> | ||
| 116 | + </div><!-- /.box-header --> | ||
| 117 | + <div class="box-body table-responsive no-padding"> | ||
| 118 | + <table class="table table-hover"> | ||
| 119 | + <tr> | ||
| 120 | + <td><b>Причина</b></td> | ||
| 121 | + <td><b>Заказов, шт.</b></td> | ||
| 122 | + <td><b>На сумму, грн.</b></td> | ||
| 123 | + </tr> | ||
| 124 | + <?php | ||
| 125 | + foreach ($rejectionStatistics as $name => $statistic) { | ||
| 126 | + ?> | ||
| 127 | + <tr> | ||
| 128 | + <td><?= $name ?></td> | ||
| 129 | + <td><?= $statistic[ 'count' ] ?></td> | ||
| 130 | + <td><?= $statistic[ 'sum' ] ?></td> | ||
| 131 | + </tr> | ||
| 132 | + <?php } ?> | ||
| 133 | + </table> | ||
| 134 | + </div><!-- /.box-body --> | ||
| 135 | +</div><!-- /.box --> | ||
| 136 | + | ||
| 137 | +<?=GridView::widget([ | ||
| 138 | + 'dataProvider' => $dataProvider, | ||
| 139 | + 'columns' => [ | ||
| 140 | + 'id', | ||
| 141 | + 'created_at:datetime', | ||
| 142 | + 'name', | ||
| 143 | + 'city', | ||
| 144 | + | ||
| 145 | + ], | ||
| 146 | + ])?> |