Commit a0da38ca8f71a10592d7b4624367d8127d869369

Authored by Alexey Boroda
2 parents 7cfb6c63 65f5712c

Merge branch 'master' of gitlab.artweb.com.ua:yarik.nechyporuk/artbox-ecommerce

controllers/OrderController.php
@@ -3,19 +3,21 @@ @@ -3,19 +3,21 @@
3 namespace artweb\artbox\ecommerce\controllers; 3 namespace artweb\artbox\ecommerce\controllers;
4 4
5 use artweb\artbox\components\SmsSender; 5 use artweb\artbox\components\SmsSender;
  6 + use artweb\artbox\ecommerce\models\OrderLabelHistory;
  7 + use artweb\artbox\ecommerce\models\OrderLog;
6 use artweb\artbox\ecommerce\models\OrderSearch; 8 use artweb\artbox\ecommerce\models\OrderSearch;
  9 + use common\components\CreditHelper;
7 use common\models\User; 10 use common\models\User;
8 - use phpDocumentor\Reflection\Types\Null_;  
9 use Yii; 11 use Yii;
10 use yii\data\ArrayDataProvider; 12 use yii\data\ArrayDataProvider;
11 - use yii\helpers\ArrayHelper; 13 + use yii\db\ActiveQuery;
12 use yii\helpers\Json; 14 use yii\helpers\Json;
13 use yii\helpers\VarDumper; 15 use yii\helpers\VarDumper;
  16 + use yii\validators\NumberValidator;
14 use yii\web\Controller; 17 use yii\web\Controller;
15 use yii\filters\VerbFilter; 18 use yii\filters\VerbFilter;
16 use yii\data\ActiveDataProvider; 19 use yii\data\ActiveDataProvider;
17 use yii\web\ForbiddenHttpException; 20 use yii\web\ForbiddenHttpException;
18 - use yii\web\HttpException;  
19 use artweb\artbox\ecommerce\models\Order; 21 use artweb\artbox\ecommerce\models\Order;
20 use artweb\artbox\ecommerce\models\OrderProduct; 22 use artweb\artbox\ecommerce\models\OrderProduct;
21 use artweb\artbox\ecommerce\models\ProductVariant; 23 use artweb\artbox\ecommerce\models\ProductVariant;
@@ -107,6 +109,14 @@ @@ -107,6 +109,14 @@
107 public function actionView($id) 109 public function actionView($id)
108 { 110 {
109 $model = $this->findModel($id); 111 $model = $this->findModel($id);
  112 +
  113 + $historyData = new ActiveDataProvider(
  114 + [
  115 + 'query' => $model->getLabelsHistory()
  116 + ->with('order', 'label', 'user'),
  117 + ]
  118 + );
  119 +
110 $dataProvider = new ActiveDataProvider( 120 $dataProvider = new ActiveDataProvider(
111 [ 121 [
112 'query' => $model->getProducts(), 122 'query' => $model->getProducts(),
@@ -115,8 +125,9 @@ @@ -115,8 +125,9 @@
115 return $this->render( 125 return $this->render(
116 'view', 126 'view',
117 [ 127 [
118 - 'model' => $model,  
119 - 'products' => $dataProvider, 128 + 'model' => $model,
  129 + 'products' => $dataProvider,
  130 + 'historyData' => $historyData,
120 ] 131 ]
121 ); 132 );
122 } 133 }
@@ -128,6 +139,25 @@ @@ -128,6 +139,25 @@
128 $model->save(); 139 $model->save();
129 } 140 }
130 141
  142 + public function actionLog($id)
  143 + {
  144 + $model = Order::findOne($id);
  145 +
  146 + $logData = new ActiveDataProvider(
  147 + [
  148 + 'query' => $model->getLogs(),
  149 + ]
  150 + );
  151 +
  152 + return $this->render(
  153 + 'log',
  154 + [
  155 + 'model' => $model,
  156 + 'logData' => $logData,
  157 + ]
  158 + );
  159 + }
  160 +
131 public function actionDelete($id) 161 public function actionDelete($id)
132 { 162 {
133 if (\Yii::$app->user->identity->isAdmin()) { 163 if (\Yii::$app->user->identity->isAdmin()) {
@@ -151,10 +181,10 @@ @@ -151,10 +181,10 @@
151 181
152 public function actionAdd() 182 public function actionAdd()
153 { 183 {
154 - if (!empty( \Yii::$app->request->post() )) { 184 + if (!empty(\Yii::$app->request->post())) {
155 $id = \Yii::$app->request->post('OrderProduct')[ 'id' ]; 185 $id = \Yii::$app->request->post('OrderProduct')[ 'id' ];
156 $order_id = \Yii::$app->request->post('OrderProduct')[ 'order_id' ]; 186 $order_id = \Yii::$app->request->post('OrderProduct')[ 'order_id' ];
157 - if (!empty( \Yii::$app->request->post('OrderProduct')[ 'count' ] )) { 187 + if (!empty(\Yii::$app->request->post('OrderProduct')[ 'count' ])) {
158 $count = \Yii::$app->request->post('OrderProduct')[ 'count' ]; 188 $count = \Yii::$app->request->post('OrderProduct')[ 'count' ];
159 } else { 189 } else {
160 $count = 1; 190 $count = 1;
@@ -174,7 +204,7 @@ @@ -174,7 +204,7 @@
174 ) 204 )
175 ->one(); 205 ->one();
176 206
177 - if (!empty( $model )) { 207 + if (!empty($model)) {
178 $model->count += $count; 208 $model->count += $count;
179 $model->removed = false; 209 $model->removed = false;
180 } else { 210 } else {
@@ -221,7 +251,7 @@ @@ -221,7 +251,7 @@
221 if ($orderProduct->load($post)) { 251 if ($orderProduct->load($post)) {
222 $orderProduct->save(); 252 $orderProduct->save();
223 $output = ''; 253 $output = '';
224 - if (isset( $posted[ 'count' ] )) { 254 + if (isset($posted[ 'count' ])) {
225 $output = Yii::$app->formatter->asDecimal($orderProduct->count, 0); 255 $output = Yii::$app->formatter->asDecimal($orderProduct->count, 0);
226 } 256 }
227 $out = Json::encode( 257 $out = Json::encode(
@@ -283,7 +313,7 @@ @@ -283,7 +313,7 @@
283 return $this->renderPartial( 313 return $this->renderPartial(
284 'print', 314 'print',
285 [ 315 [
286 - 'order' => $order, 316 + 'order' => $order,
287 'dataProvider' => $dataProvider, 317 'dataProvider' => $dataProvider,
288 ] 318 ]
289 ); 319 );
@@ -309,7 +339,7 @@ @@ -309,7 +339,7 @@
309 $orderProduct->save(); 339 $orderProduct->save();
310 $orderProduct->order->totalRecount(); 340 $orderProduct->order->totalRecount();
311 $output = ''; 341 $output = '';
312 - if (isset( $posted[ 'count' ] )) { 342 + if (isset($posted[ 'count' ])) {
313 $output = Yii::$app->formatter->asDecimal($orderProduct->count, 0); 343 $output = Yii::$app->formatter->asDecimal($orderProduct->count, 0);
314 } 344 }
315 $out = Json::encode( 345 $out = Json::encode(
@@ -322,9 +352,21 @@ @@ -322,9 +352,21 @@
322 352
323 return $out; 353 return $out;
324 } 354 }
325 - 355 +
326 $model = $this->findModel($id); 356 $model = $this->findModel($id);
327 357
  358 + if ($model->payment == 10) {
  359 + $model->validators->append(
  360 + new NumberValidator(
  361 + [
  362 + 'attributes' => 'credit_sum',
  363 + 'max' => $model->total - CreditHelper::MIN_CREDIT_SUM,
  364 + 'min' => $model->total - CreditHelper::MAX_CREDIT_SUM,
  365 + ]
  366 + )
  367 + );
  368 + }
  369 +
328 /** 370 /**
329 * @var User $user 371 * @var User $user
330 */ 372 */
@@ -334,7 +376,7 @@ @@ -334,7 +376,7 @@
334 throw new ForbiddenHttpException(); 376 throw new ForbiddenHttpException();
335 } 377 }
336 } 378 }
337 - 379 +
338 $dataProvider = new ActiveDataProvider( 380 $dataProvider = new ActiveDataProvider(
339 [ 381 [
340 'query' => $model->getProducts() 382 'query' => $model->getProducts()
@@ -344,10 +386,10 @@ @@ -344,10 +386,10 @@
344 ] 386 ]
345 ); 387 );
346 388
347 - if (empty( $model->manager_id )) { 389 + if (empty($model->manager_id)) {
348 $model->manager_id = \Yii::$app->user->id; 390 $model->manager_id = \Yii::$app->user->id;
349 } 391 }
350 - 392 +
351 $headers = \Yii::$app->response->headers; 393 $headers = \Yii::$app->response->headers;
352 $headers->set('Access-Control-Allow-Origin', '*'); 394 $headers->set('Access-Control-Allow-Origin', '*');
353 395
@@ -392,7 +434,7 @@ @@ -392,7 +434,7 @@
392 } 434 }
393 } 435 }
394 436
395 - public function actionFindProduct($q = null, $id = null) 437 + public function actionFindProduct($q = NULL, $id = NULL)
396 { 438 {
397 \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 439 \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
398 $out = [ 440 $out = [
@@ -452,7 +494,7 @@ @@ -452,7 +494,7 @@
452 494
453 protected function findModel($id) 495 protected function findModel($id)
454 { 496 {
455 - if (( $model = Order::findOne($id) ) !== null) { 497 + if (( $model = Order::findOne($id) ) !== NULL) {
456 return $model; 498 return $model;
457 } else { 499 } else {
458 throw new NotFoundHttpException('The requested page does not exist.'); 500 throw new NotFoundHttpException('The requested page does not exist.');
@@ -469,7 +511,7 @@ @@ -469,7 +511,7 @@
469 if ($model->edit_id == \Yii::$app->user->id) { 511 if ($model->edit_id == \Yii::$app->user->id) {
470 $this->unblockOrder(\Yii::$app->request->post('id')); 512 $this->unblockOrder(\Yii::$app->request->post('id'));
471 } 513 }
472 - 514 +
473 if (!$model->published) { 515 if (!$model->published) {
474 $model->deleteUnpublished(); 516 $model->deleteUnpublished();
475 } 517 }
@@ -495,7 +537,7 @@ @@ -495,7 +537,7 @@
495 537
496 public function actionBlockOrder() 538 public function actionBlockOrder()
497 { 539 {
498 - if (!empty( \Yii::$app->request->post() )) { 540 + if (!empty(\Yii::$app->request->post())) {
499 \Yii::$app->response->format = Response::FORMAT_JSON; 541 \Yii::$app->response->format = Response::FORMAT_JSON;
500 542
501 $model = $this->findModel(\Yii::$app->request->post('id')); 543 $model = $this->findModel(\Yii::$app->request->post('id'));
@@ -512,7 +554,7 @@ @@ -512,7 +554,7 @@
512 if ($model->save()) { 554 if ($model->save()) {
513 return [ 555 return [
514 'time' => $date, 556 'time' => $date,
515 - 'user' => !empty( $user ) ? $user->username : '', 557 + 'user' => !empty($user) ? $user->username : '',
516 ]; 558 ];
517 } else { 559 } else {
518 return [ 560 return [
@@ -540,6 +582,18 @@ @@ -540,6 +582,18 @@
540 } 582 }
541 $model->published = true; 583 $model->published = true;
542 $model->save(); 584 $model->save();
  585 +
  586 + /**
  587 + * Add order to history
  588 + */
  589 + $history = new OrderLabelHistory();
  590 +
  591 + $history->label_id = (integer) $model->label;
  592 + $history->order_id = (integer) $model->id;
  593 + $history->user_id = (integer) \Yii::$app->user->identity->id;
  594 +
  595 + $history->save();
  596 +
543 /** 597 /**
544 * @var SmsSender $sender 598 * @var SmsSender $sender
545 */ 599 */
controllers/StatisticsController.php
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 use artweb\artbox\ecommerce\models\Label; 5 use artweb\artbox\ecommerce\models\Label;
6 use artweb\artbox\ecommerce\models\Order; 6 use artweb\artbox\ecommerce\models\Order;
  7 + use common\models\User;
7 use yii\data\ActiveDataProvider; 8 use yii\data\ActiveDataProvider;
8 use yii\helpers\ArrayHelper; 9 use yii\helpers\ArrayHelper;
9 use yii\helpers\VarDumper; 10 use yii\helpers\VarDumper;
@@ -11,7 +12,7 @@ @@ -11,7 +12,7 @@
11 12
12 class StatisticsController extends Controller 13 class StatisticsController extends Controller
13 { 14 {
14 - public function actionIndex($date_range = NULL, $label = NULL) 15 + public function actionIndex($date_range = NULL, $label = NULL, $manager = NULL)
15 { 16 {
16 /** 17 /**
17 * Get a dates range 18 * Get a dates range
@@ -34,6 +35,12 @@ @@ -34,6 +35,12 @@
34 } else { 35 } else {
35 $labelFilter = []; 36 $labelFilter = [];
36 } 37 }
  38 +
  39 + if (!empty($manager)) {
  40 + $managerFilter = [ 'manager_id' => $manager ];
  41 + } else {
  42 + $managerFilter = [];
  43 + }
37 44
38 /** 45 /**
39 * Get labels 46 * Get labels
@@ -41,61 +48,137 @@ @@ -41,61 +48,137 @@
41 $labels = Label::find() 48 $labels = Label::find()
42 ->with('lang') 49 ->with('lang')
43 ->all(); 50 ->all();
  51 +
  52 + /**
  53 + * Get user
  54 + */
  55 + $managers = User::find()
  56 + ->all();
44 57
45 /** 58 /**
46 * Generate statistics 59 * Generate statistics
47 */ 60 */
48 $labelStatistics = ArrayHelper::map( 61 $labelStatistics = ArrayHelper::map(
49 $labels, 62 $labels,
50 - function($model) {  
51 - /**  
52 - * @var Label $model  
53 - */ 63 + function(Label $model) {
54 return $model->lang->title; 64 return $model->lang->title;
55 }, 65 },
56 - function($model) use ($dateFilter) {  
57 - /**  
58 - * @var Label $model  
59 - */  
60 - return $model->getStatistics($dateFilter); 66 + function(Label $model) use ($dateFilter, $managerFilter) {
  67 + return $model->getStatistics($dateFilter, $managerFilter);
61 } 68 }
62 ); 69 );
63 - 70 +
  71 + /**
  72 + * Data provider for table
  73 + */
64 $dataProvider = new ActiveDataProvider( 74 $dataProvider = new ActiveDataProvider(
65 [ 75 [
66 'query' => Order::find() 76 'query' => Order::find()
67 ->filterWhere($dateFilter) 77 ->filterWhere($dateFilter)
  78 + ->andFilterWhere($managerFilter)
68 ->andFilterWhere($labelFilter), 79 ->andFilterWhere($labelFilter),
69 ] 80 ]
70 ); 81 );
  82 +
  83 + /**
  84 + * Creating charts data
  85 + */
  86 + $labelChartData1 = [
  87 + 'labels' => array_keys($labelStatistics),
  88 + 'datasets' => [
  89 + [
  90 + 'label' => 'Заказов, шт.',
  91 + 'data' => ArrayHelper::getColumn($labelStatistics, 'count', false),
  92 + 'backgroundColor' => 'rgba(54, 162, 235, 0.2)',
  93 + 'borderColor' => 'rgba(54, 162, 235, 1)',
  94 + 'borderWidth' => 1,
  95 + ],
  96 + ],
  97 + ];
71 98
72 - $chartData = [];  
73 - foreach ($labelStatistics as $statistic) {  
74 - $chartData[] = $statistic[ 'sum' ];  
75 - }  
76 - $chartLabels = [];  
77 - foreach ($labelStatistics as $name => $statistic) {  
78 - $chartLabels[] = $name;  
79 - }  
80 - $labelChartData = [  
81 - 'labels' => $chartLabels, 99 + $labelChartData2 = [
  100 + 'labels' => array_keys($labelStatistics),
  101 + 'datasets' => [
  102 + [
  103 + 'label' => 'На сумму, грн.',
  104 + 'data' => ArrayHelper::getColumn($labelStatistics, 'sum', false),
  105 + 'backgroundColor' => 'rgba(255, 99, 132, 0.2)',
  106 + 'borderColor' => 'rgba(255,99,132,1)',
  107 + 'borderWidth' => 1,
  108 + ],
  109 + ],
  110 + ];
  111 +
  112 + $labelChartData3 = [
  113 + 'labels' => array_keys($labelStatistics),
82 'datasets' => [ 114 'datasets' => [
83 [ 115 [
84 - 'label' => 'На сумму, грн.',  
85 - 'data' => $chartData, 116 + 'label' => 'Заказано товаров, шт.',
  117 + 'data' => ArrayHelper::getColumn($labelStatistics, 'products', false),
  118 + 'backgroundColor' => 'rgba(255, 206, 86, 0.2)',
  119 + 'borderColor' => 'rgba(255, 206, 86, 1)',
  120 + 'borderWidth' => 1,
  121 + ],
  122 + [
  123 + 'label' => 'Уникальных товаров, шт.',
  124 + 'data' => ArrayHelper::getColumn($labelStatistics, 'unique', false),
  125 + 'backgroundColor' => 'rgba(75, 192, 192, 0.2)',
  126 + 'borderColor' => 'rgba(75, 192, 192, 1)',
  127 + 'borderWidth' => 1,
86 ], 128 ],
87 ], 129 ],
88 ]; 130 ];
  131 +
  132 + /**
  133 + * Getting rejection statistics
  134 + */
  135 + $rejectStatistics = Order::getRejectionStatistics($dateFilter, $managerFilter);
  136 +
  137 + /**
  138 + * Charts data for rejects
  139 + */
  140 + $rejectChartData1 = [
  141 + 'labels' => array_keys($rejectStatistics),
  142 + 'datasets' => [
  143 + [
  144 + 'label' => 'Заказов, шт.',
  145 + 'data' => ArrayHelper::getColumn($rejectStatistics, 'count', false),
  146 + 'backgroundColor' => 'rgba(153, 102, 255, 0.2)',
  147 + 'borderColor' => 'rgba(153, 102, 255, 1)',
  148 + 'borderWidth' => 1,
  149 + ],
  150 + ],
  151 + ];
  152 +
  153 + $rejectChartData2 = [
  154 + 'labels' => array_keys($rejectStatistics),
  155 + 'datasets' => [
  156 + [
  157 + 'label' => 'На сумму, грн.',
  158 + 'data' => ArrayHelper::getColumn($rejectStatistics, 'sum', false),
  159 + 'backgroundColor' => 'rgba(255, 159, 64, 0.2)',
  160 + 'borderColor' => 'rgba(255, 159, 64, 1)',
  161 + 'borderWidth' => 1,
  162 + ],
  163 + ],
  164 + ];
  165 +
89 return $this->render( 166 return $this->render(
90 'index', 167 'index',
91 [ 168 [
92 'labels' => $labels, 169 'labels' => $labels,
  170 + 'managers' => $managers,
93 'labelStatistics' => $labelStatistics, 171 'labelStatistics' => $labelStatistics,
94 - 'rejectionStatistics' => Order::getRejectionStatistics($dateFilter), 172 + 'rejectionStatistics' => $rejectStatistics,
95 'dataProvider' => $dataProvider, 173 'dataProvider' => $dataProvider,
96 - 'labelChartData' => $labelChartData, 174 + 'labelChartData1' => $labelChartData1,
  175 + 'labelChartData2' => $labelChartData2,
  176 + 'labelChartData3' => $labelChartData3,
  177 + 'rejectChartData1' => $rejectChartData1,
  178 + 'rejectChartData2' => $rejectChartData2,
97 'dateValue' => empty($date_range) ? '' : $date_range, 179 'dateValue' => empty($date_range) ? '' : $date_range,
98 'dataLabel' => empty($label) ? false : $label, 180 'dataLabel' => empty($label) ? false : $label,
  181 + 'dataManager' => empty($manager) ? false : $manager,
99 ] 182 ]
100 ); 183 );
101 } 184 }
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 /** 10 /**
11 * Class Basket to work with basket 11 * Class Basket to work with basket
12 * 12 *
  13 + * @property bool isCredit
13 * @package artweb\artbox\ecommerce\models 14 * @package artweb\artbox\ecommerce\models
14 */ 15 */
15 class Basket extends Component 16 class Basket extends Component
@@ -32,7 +33,7 @@ @@ -32,7 +33,7 @@
32 $this->session = \Yii::$app->session; 33 $this->session = \Yii::$app->session;
33 if (!$this->session->has('basket')) { 34 if (!$this->session->has('basket')) {
34 $this->session->set('basket', []); 35 $this->session->set('basket', []);
35 - } elseif(!empty($this->session->get('basket'))) { 36 + } elseif (!empty( $this->session->get('basket') )) {
36 $cookies = \Yii::$app->response->cookies; 37 $cookies = \Yii::$app->response->cookies;
37 $cookies->add( 38 $cookies->add(
38 new Cookie( 39 new Cookie(
@@ -144,8 +145,9 @@ @@ -144,8 +145,9 @@
144 { 145 {
145 $this->session->set('basket', $data); 146 $this->session->set('basket', $data);
146 $cookies = \Yii::$app->response->cookies; 147 $cookies = \Yii::$app->response->cookies;
147 - if(empty($data)) { 148 + if (empty( $data )) {
148 $cookies->remove('basket'); 149 $cookies->remove('basket');
  150 + $cookies->remove('isCredit');
149 } else { 151 } else {
150 $cookies->add( 152 $cookies->add(
151 new Cookie( 153 new Cookie(
@@ -247,6 +249,23 @@ @@ -247,6 +249,23 @@
247 public function clear() 249 public function clear()
248 { 250 {
249 $this->setData([]); 251 $this->setData([]);
  252 + \Yii::$app->response->cookies->remove('isCredit');
  253 + }
  254 +
  255 + /**
  256 + * Check if is credit cookie flag set
  257 + *
  258 + * @return bool
  259 + */
  260 + public static function getIsCredit(): bool
  261 + {
  262 + // Get cookies from global in order to skip yii2 cookie validation
  263 + $cookies = $_COOKIE;
  264 + if (isset( $cookies[ 'isCredit' ] )) {
  265 + return true;
  266 + } else {
  267 + return false;
  268 + }
250 } 269 }
251 270
252 } 271 }
@@ -65,40 +65,43 @@ @@ -65,40 +65,43 @@
65 ]; 65 ];
66 } 66 }
67 67
68 - public function getStatistics(array $where = []) 68 + public function getStatistics(array $date = [], array $manager = [])
69 { 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 - 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 + $date
  83 + )
  84 + ->andFilterWhere($manager),
  85 + 'products' => ( new Query() )->select('SUM(count)')
  86 + ->from('order')
  87 + ->leftJoin(
  88 + 'order_product',
  89 + '"order"."id"="order_product"."order_id"'
  90 + )
  91 + ->where([ 'order.label' => $this->id ])
  92 + ->andFilterWhere(
  93 + $date
  94 + )
  95 + ->andFilterWhere($manager),
  96 + ]
  97 + )
  98 + ->from('order')
  99 + ->where([ 'label' => $this->id ])
  100 + ->andFilterWhere(
  101 + $date
  102 + )
  103 + ->andFilterWhere($manager);
  104 +
102 return $query->one(); 105 return $query->one();
103 } 106 }
104 } 107 }
@@ -8,6 +8,8 @@ @@ -8,6 +8,8 @@
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 use yii\db\Query;
  11 + use yii\helpers\Json;
  12 + use yii\helpers\VarDumper;
11 13
12 /** 14 /**
13 * Class Order 15 * Class Order
@@ -55,6 +57,12 @@ @@ -55,6 +57,12 @@
55 * @property string $city 57 * @property string $city
56 * @property string $deliveryString 58 * @property string $deliveryString
57 * @property boolean $published 59 * @property boolean $published
  60 + * @property Label $orderLabel
  61 + * @property Delivery $orderDelivery
  62 + * @property OrderPayment $orderPayment
  63 + * @property OrderLog[] $logs
  64 + * @property float $credit_sum
  65 + * @property int $credit_month
58 */ 66 */
59 class Order extends ActiveRecord 67 class Order extends ActiveRecord
60 { 68 {
@@ -92,13 +100,14 @@ @@ -92,13 +100,14 @@
92 { 100 {
93 return 'order'; 101 return 'order';
94 } 102 }
95 - 103 +
96 /** 104 /**
97 - * @param array $where 105 + * @param array $date
  106 + * @param array $manager
98 * 107 *
99 * @return array 108 * @return array
100 */ 109 */
101 - public static function getRejectionStatistics(array $where = []) 110 + public static function getRejectionStatistics(array $date = [], array $manager = [])
102 { 111 {
103 $result = []; 112 $result = [];
104 foreach (self::REASONS as $id => $reason) { 113 foreach (self::REASONS as $id => $reason) {
@@ -113,12 +122,87 @@ @@ -113,12 +122,87 @@
113 [ 122 [
114 'reason' => $id, 123 'reason' => $id,
115 ] 124 ]
116 - )->andFilterWhere($where)->one(); 125 + )
  126 + ->andFilterWhere($date)
  127 + ->andFilterWhere($manager)
  128 + ->one();
117 } 129 }
118 130
119 return $result; 131 return $result;
120 } 132 }
121 133
  134 + /**
  135 + * @param string $attr
  136 + * @param array $values
  137 + *
  138 + * @return array
  139 + * Return array in form ['old'=>'old value ...', 'new' => 'new value ...']
  140 + */
  141 + public function getLogAttributes(string $attr, array $values)
  142 + {
  143 + if ($attr == 'deadline') {
  144 + return [
  145 + 'old' => empty($values[ 'old' ]) ? '' : date('d.m.Y', $values[ 'old' ]),
  146 + 'new' => empty($values[ 'new' ]) ? '' : date('d.m.Y', $values[ 'new' ]),
  147 + ];
  148 + } elseif ($attr == 'reason') {
  149 + return [
  150 + 'old' => empty($values[ 'old' ]) ? '' : self::REASONS[ $values[ 'old' ] ],
  151 + 'new' => empty($values[ 'new' ]) ? '' : self::REASONS[ $values[ 'new' ] ],
  152 + ];
  153 + } elseif ($attr == 'label') {
  154 + $labels = Label::find()
  155 + ->with('lang')
  156 + ->indexBy('id')
  157 + ->all();
  158 + return [
  159 + 'old' => empty($values[ 'old' ]) ? '' : $labels[ $values[ 'old' ] ]->lang->title,
  160 + 'new' => empty($values[ 'new' ]) ? '' : $labels[ $values[ 'new' ] ]->lang->title,
  161 + ];
  162 + } elseif ($attr == 'delivery') {
  163 + $deliveries = Delivery::find()
  164 + ->with('lang')
  165 + ->indexBy('id')
  166 + ->all();
  167 + return [
  168 + 'old' => empty($values[ 'old' ]) ? '' : $deliveries[ $values[ 'old' ] ]->lang->title,
  169 + 'new' => empty($values[ 'new' ]) ? '' : $deliveries[ $values[ 'new' ] ]->lang->title,
  170 + ];
  171 + } elseif ($attr == 'manager_id') {
  172 + $users = User::find()
  173 + ->indexBy('id')
  174 + ->all();
  175 + return [
  176 + 'old' => empty($values[ 'old' ]) ? '' : $users[ $values[ 'old' ] ]->username,
  177 + 'new' => empty($values[ 'new' ]) ? '' : $users[ $values[ 'new' ] ]->username,
  178 + ];
  179 + } elseif ($attr == 'payment') {
  180 + $payment = OrderPayment::find()
  181 + ->with('lang')
  182 + ->indexBy('id')
  183 + ->all();
  184 + return [
  185 + 'old' => empty($values[ 'old' ]) ? '' : $payment[ $values[ 'old' ] ]->lang->title,
  186 + 'new' => empty($values[ 'new' ]) ? '' : $payment[ $values[ 'new' ] ]->lang->title,
  187 + ];
  188 + } elseif ($attr == 'shipping_by') {
  189 + return [
  190 + 'old' => empty($values[ 'old' ]) ? '' : self::SHIPPING_BY[ $values[ 'old' ] ][ 'label' ],
  191 + 'new' => empty($values[ 'new' ]) ? '' : self::SHIPPING_BY[ $values[ 'new' ] ][ 'label' ],
  192 + ];
  193 + } elseif ($attr == 'pay') {
  194 + return [
  195 + 'old' => ( $values[ 'old' ] == true ) ? 'Оплачен' : 'Не оплачен',
  196 + 'new' => ( $values[ 'new' ] == true ) ? 'Оплачен' : 'Не оплачен',
  197 + ];
  198 + } else {
  199 + return $values;
  200 + }
  201 + }
  202 +
  203 + /**
  204 + * @inheritdoc
  205 + */
122 public function behaviors() 206 public function behaviors()
123 { 207 {
124 return [ 208 return [
@@ -131,6 +215,9 @@ @@ -131,6 +215,9 @@
131 ]; 215 ];
132 } 216 }
133 217
  218 + /**
  219 + * @inheritdoc
  220 + */
134 public function rules() 221 public function rules()
135 { 222 {
136 return [ 223 return [
@@ -188,6 +275,21 @@ @@ -188,6 +275,21 @@
188 ], 275 ],
189 [ 276 [
190 [ 277 [
  278 + 'credit_month',
  279 + ],
  280 + 'integer',
  281 + 'min' => 3,
  282 + 'max' => 36,
  283 + ],
  284 + [
  285 + [
  286 + 'credit_sum',
  287 + ],
  288 + 'number',
  289 + 'min' => 0,
  290 + ],
  291 + [
  292 + [
191 'deadline', 293 'deadline',
192 'name', 294 'name',
193 'numbercard', 295 'numbercard',
@@ -209,6 +311,49 @@ @@ -209,6 +311,49 @@
209 ]; 311 ];
210 } 312 }
211 313
  314 + public function afterSave($insert, $changedAttributes)
  315 + {
  316 + $data = [];
  317 + foreach ($changedAttributes as $key => $attribute) {
  318 + if ($this->oldAttributes[ $key ] != $attribute && $key != 'updated_at') {
  319 + $data[ $key ] = $this->getLogAttributes(
  320 + $key,
  321 + [
  322 + 'old' => $attribute,
  323 + 'new' => $this->oldAttributes[ $key ],
  324 + ]
  325 + );
  326 + }
  327 + }
  328 +
  329 + if (!empty($data) && empty($data[ 'edit_time' ])) {
  330 + $log = new OrderLog();
  331 + $log->order_id = (integer) $this->id;
  332 + $log->user_id = (integer) \Yii::$app->user->identity->id;
  333 + $log->data = Json::encode($data);
  334 +
  335 + $log->save();
  336 + }
  337 +
  338 + if (!empty($changedAttributes[ 'label' ])) {
  339 + if ($this->label != (string) $changedAttributes[ 'label' ]) {
  340 + $history = new OrderLabelHistory();
  341 +
  342 + $history->label_id = (integer) $this->label;
  343 + $history->order_id = (integer) $this->id;
  344 + $history->user_id = (integer) \Yii::$app->user->identity->id;
  345 +
  346 + if ($history->save()) {
  347 + \Yii::$app->session->setFlash('label_update', 'Статус заказа обновлен');
  348 + }
  349 + }
  350 + }
  351 + parent::afterSave($insert, $changedAttributes);
  352 + }
  353 +
  354 + /**
  355 + * @inheritdoc
  356 + */
212 public function afterFind() 357 public function afterFind()
213 { 358 {
214 parent::afterFind(); 359 parent::afterFind();
@@ -216,6 +361,9 @@ @@ -216,6 +361,9 @@
216 361
217 } 362 }
218 363
  364 + /**
  365 + * @inheritdoc
  366 + */
219 public function beforeSave($insert) 367 public function beforeSave($insert)
220 { 368 {
221 if (parent::beforeSave($insert)) { 369 if (parent::beforeSave($insert)) {
@@ -227,6 +375,9 @@ @@ -227,6 +375,9 @@
227 375
228 } 376 }
229 377
  378 + /**
  379 + * Convert some date
  380 + */
230 protected function convertDate() 381 protected function convertDate()
231 { 382 {
232 if (!empty($this->deadline)) { 383 if (!empty($this->deadline)) {
@@ -239,6 +390,9 @@ @@ -239,6 +390,9 @@
239 390
240 } 391 }
241 392
  393 + /**
  394 + * @inheritdoc
  395 + */
242 public function attributeLabels() 396 public function attributeLabels()
243 { 397 {
244 return [ 398 return [
@@ -273,9 +427,14 @@ @@ -273,9 +427,14 @@
273 'shipping_by' => Yii::t('app', 'Отправка за счет'), 427 'shipping_by' => Yii::t('app', 'Отправка за счет'),
274 'city' => Yii::t('app', 'Город'), 428 'city' => Yii::t('app', 'Город'),
275 'numbercard' => Yii::t('app', '№ карточки'), 429 'numbercard' => Yii::t('app', '№ карточки'),
  430 + 'credit_month' => Yii::t('app', 'Количество месяцев'),
  431 + 'credit_sum' => Yii::t('app', 'Первоначальный взнос'),
276 ]; 432 ];
277 } 433 }
278 434
  435 + /**
  436 + * @return \yii\db\ActiveQuery
  437 + */
279 public function getUser() 438 public function getUser()
280 { 439 {
281 return $this->hasOne(Customer::className(), [ 'id' => 'user_id' ]); 440 return $this->hasOne(Customer::className(), [ 'id' => 'user_id' ]);
@@ -314,6 +473,14 @@ @@ -314,6 +473,14 @@
314 } 473 }
315 474
316 /** 475 /**
  476 + * @return \yii\db\ActiveQuery
  477 + */
  478 + public function getLabelsHistory()
  479 + {
  480 + return $this->hasMany(OrderLabelHistory::className(), [ 'order_id' => 'id' ]);
  481 + }
  482 +
  483 + /**
317 * @return string 484 * @return string
318 */ 485 */
319 public function getDeliveryString() 486 public function getDeliveryString()
@@ -330,6 +497,14 @@ @@ -330,6 +497,14 @@
330 } 497 }
331 498
332 /** 499 /**
  500 + * @return \yii\db\ActiveQuery
  501 + */
  502 + public function getLogs()
  503 + {
  504 + return $this->hasMany(OrderLog::className(), [ 'order_id' => 'id' ]);
  505 + }
  506 +
  507 + /**
333 * If deadline is fucked up returns true, 508 * If deadline is fucked up returns true,
334 * if deadline is not setted return false, like everything is ok 509 * if deadline is not setted return false, like everything is ok
335 * 510 *
@@ -345,13 +520,18 @@ @@ -345,13 +520,18 @@
345 } 520 }
346 521
347 /** 522 /**
348 - * 523 + * @return \yii\db\ActiveQuery
349 */ 524 */
350 public function getManager() 525 public function getManager()
351 { 526 {
352 return $this->hasOne(User::className(), [ 'id' => 'manager_id' ]); 527 return $this->hasOne(User::className(), [ 'id' => 'manager_id' ]);
353 } 528 }
354 529
  530 + /**
  531 + * Check if order is blocked for updating
  532 + *
  533 + * @return bool
  534 + */
355 public function isBlocked() 535 public function isBlocked()
356 { 536 {
357 if ($this->edit_id === 0) { 537 if ($this->edit_id === 0) {
@@ -365,6 +545,9 @@ @@ -365,6 +545,9 @@
365 } 545 }
366 } 546 }
367 547
  548 + /**
  549 + * If order products changed recount te total value
  550 + */
368 public function totalRecount() 551 public function totalRecount()
369 { 552 {
370 $products = $this->products; 553 $products = $this->products;
@@ -379,6 +562,9 @@ @@ -379,6 +562,9 @@
379 $this->save(); 562 $this->save();
380 } 563 }
381 564
  565 + /**
  566 + * If exit unpublished order - delete it
  567 + */
382 public function deleteUnpublished() 568 public function deleteUnpublished()
383 { 569 {
384 /** 570 /**
models/OrderLabelHistory.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artweb\artbox\ecommerce\models;
  4 +
  5 + use yii\behaviors\TimestampBehavior;
  6 + use yii\db\ActiveRecord;
  7 + use common\models\User;
  8 + use Yii;
  9 +
  10 + /**
  11 + * This is the model class for table "order_label_history".
  12 + *
  13 + * @property integer $id
  14 + * @property integer $label_id
  15 + * @property integer $order_id
  16 + * @property integer $user_id
  17 + * @property integer $created_at
  18 + * @property Order $order
  19 + * @property Label $label
  20 + * @property User $user
  21 + */
  22 + class OrderLabelHistory extends ActiveRecord
  23 + {
  24 + /**
  25 + * @inheritdoc
  26 + */
  27 + public static function tableName()
  28 + {
  29 + return 'order_label_history';
  30 + }
  31 +
  32 + /**
  33 + * @inheritdoc
  34 + */
  35 + public function behaviors()
  36 + {
  37 + return [
  38 + [
  39 + 'class' => TimestampBehavior::className(),
  40 + 'updatedAtAttribute' => false,
  41 + ],
  42 + ];
  43 + }
  44 +
  45 + /**
  46 + * @inheritdoc
  47 + */
  48 + public function rules()
  49 + {
  50 + return [
  51 + [
  52 + [
  53 + 'label_id',
  54 + 'order_id',
  55 + 'user_id',
  56 + 'created_at',
  57 + ],
  58 + 'integer',
  59 + ],
  60 + [
  61 + [ 'order_id' ],
  62 + 'exist',
  63 + 'skipOnError' => true,
  64 + 'targetClass' => Order::className(),
  65 + 'targetAttribute' => [ 'order_id' => 'id' ],
  66 + ],
  67 + [
  68 + [ 'label_id' ],
  69 + 'exist',
  70 + 'skipOnError' => true,
  71 + 'targetClass' => Label::className(),
  72 + 'targetAttribute' => [ 'label_id' => 'id' ],
  73 + ],
  74 +// [
  75 +// [ 'user_id' ],
  76 +// 'exist',
  77 +// 'skipOnError' => true,
  78 +// 'targetClass' => User::className(),
  79 +// 'targetAttribute' => [ 'user_id' => 'id' ],
  80 +// ],
  81 + ];
  82 + }
  83 +
  84 + /**
  85 + * @inheritdoc
  86 + */
  87 + public function attributeLabels()
  88 + {
  89 + return [
  90 + 'id' => Yii::t('app', 'ID'),
  91 + 'label_id' => Yii::t('app', 'Label ID'),
  92 + 'order_id' => Yii::t('app', 'Order ID'),
  93 + 'user_id' => Yii::t('app', 'User ID'),
  94 + 'created_at' => Yii::t('app', 'Created At'),
  95 + ];
  96 + }
  97 +
  98 + /**
  99 + * @return \yii\db\ActiveQuery
  100 + */
  101 + public function getOrder()
  102 + {
  103 + return $this->hasOne(Order::className(), [ 'id' => 'order_id' ]);
  104 + }
  105 +
  106 + /**
  107 + * @return \yii\db\ActiveQuery
  108 + */
  109 + public function getLabel()
  110 + {
  111 + return $this->hasOne(Label::className(), [ 'id' => 'label_id' ]);
  112 + }
  113 +
  114 + /**
  115 + * @return \yii\db\ActiveQuery
  116 + */
  117 + public function getUser()
  118 + {
  119 + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]);
  120 + }
  121 + }
models/OrderLog.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace artweb\artbox\ecommerce\models;
  4 +
  5 + use common\models\User;
  6 + use Yii;
  7 + use yii\behaviors\TimestampBehavior;
  8 + use yii\db\ActiveRecord;
  9 +
  10 + /**
  11 + * This is the model class for table "order_log".
  12 + *
  13 + * @property integer $id
  14 + * @property integer $order_id
  15 + * @property integer $created_at
  16 + * @property integer $user_id
  17 + * @property string $data
  18 + * @property Order $order
  19 + * @property User $user
  20 + */
  21 + class OrderLog extends ActiveRecord
  22 + {
  23 + /**
  24 + * @inheritdoc
  25 + */
  26 + public static function tableName()
  27 + {
  28 + return 'order_log';
  29 + }
  30 +
  31 + /**
  32 + * @inheritdoc
  33 + */
  34 + public function behaviors()
  35 + {
  36 + return [
  37 + [
  38 + 'class' => TimestampBehavior::className(),
  39 + 'updatedAtAttribute' => false,
  40 + ],
  41 + ];
  42 + }
  43 +
  44 + /**
  45 + * @inheritdoc
  46 + */
  47 + public function rules()
  48 + {
  49 + return [
  50 + [
  51 + [
  52 + 'order_id',
  53 + 'created_at',
  54 + 'user_id',
  55 + ],
  56 + 'integer',
  57 + ],
  58 + [
  59 + [ 'data' ],
  60 + 'string',
  61 + ],
  62 + [
  63 + [ 'order_id' ],
  64 + 'exist',
  65 + 'skipOnError' => true,
  66 + 'targetClass' => Order::className(),
  67 + 'targetAttribute' => [ 'order_id' => 'id' ],
  68 + ],
  69 + // [
  70 + // [ 'user_id' ],
  71 + // 'exist',
  72 + // 'skipOnError' => true,
  73 + // 'targetClass' => User::className(),
  74 + // 'targetAttribute' => [ 'user_id' => 'id' ],
  75 + // ],
  76 + ];
  77 + }
  78 +
  79 + /**
  80 + * @inheritdoc
  81 + */
  82 + public function attributeLabels()
  83 + {
  84 + return [
  85 + 'id' => Yii::t('app', 'ID'),
  86 + 'order_id' => Yii::t('app', 'Order ID'),
  87 + 'created_at' => Yii::t('app', 'Created At'),
  88 + 'user_id' => Yii::t('app', 'User ID'),
  89 + 'data' => Yii::t('app', 'Data'),
  90 + ];
  91 + }
  92 +
  93 + /**
  94 + * @return \yii\db\ActiveQuery
  95 + */
  96 + public function getOrder()
  97 + {
  98 + return $this->hasOne(Order::className(), [ 'id' => 'order_id' ]);
  99 + }
  100 +
  101 + /**
  102 + * @return \yii\db\ActiveQuery
  103 + */
  104 + public function getUser()
  105 + {
  106 + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]);
  107 + }
  108 + }
models/Product.php
@@ -571,7 +571,40 @@ @@ -571,7 +571,40 @@
571 } 571 }
572 return $groups; 572 return $groups;
573 } 573 }
574 - 574 +
  575 +
  576 + /**
  577 + * Get characteristic from TaxGroups for current Product filled with $customOptions that satisfy current Product
  578 + *
  579 + * @return TaxGroup[]
  580 + */
  581 + public function getCharacteristic(): array
  582 + {
  583 + $groups = $options = [];
  584 + foreach ($this->getOptions()
  585 + ->with('lang')
  586 + ->all() as $option) {
  587 + /**
  588 + * @var TaxOption $option
  589 + */
  590 + $options[ $option[ 'tax_group_id' ] ][] = $option;
  591 + }
  592 + foreach (TaxGroup::find()
  593 + ->where(['is_menu'=>true])
  594 + ->andWhere([ 'id' => array_keys($options) ])
  595 + ->with('lang')
  596 + ->all() as $group) {
  597 + /**
  598 + * @var TaxGroup $group
  599 + */
  600 + if (!empty($options[ $group->id ])) {
  601 + $group->customOptions = $options[ $group->id ];
  602 + $groups[] = $group;
  603 + }
  604 + }
  605 + return $groups;
  606 + }
  607 +
575 public function getVideos() 608 public function getVideos()
576 { 609 {
577 return $this->hasMany(ProductVideo::className(), [ 'product_id' => 'id' ]); 610 return $this->hasMany(ProductVideo::className(), [ 'product_id' => 'id' ]);
models/ProductVariant.php
@@ -398,6 +398,38 @@ @@ -398,6 +398,38 @@
398 } 398 }
399 return $groups; 399 return $groups;
400 } 400 }
  401 +
  402 + /**
  403 + * Get characteristic from TaxGroups for current ProductVariant filled with $customOptions that satisfy current Product
  404 + *
  405 + * @return TaxGroup[]
  406 + */
  407 + public function getCharacteristic(): array
  408 + {
  409 + $groups = $options = [];
  410 + foreach ($this->getOptions()
  411 + ->with('lang')
  412 + ->all() as $option) {
  413 + /**
  414 + * @var TaxOption $option
  415 + */
  416 + $options[ $option[ 'tax_group_id' ] ][] = $option;
  417 + }
  418 + foreach (TaxGroup::find()
  419 + ->where(['is_menu'=>true])
  420 + ->andWhere([ 'id' => array_keys($options) ])
  421 + ->with('lang')
  422 + ->all() as $group) {
  423 + /**
  424 + * @var TaxGroup $group
  425 + */
  426 + if (!empty($options[ $group->id ])) {
  427 + $group->customOptions = $options[ $group->id ];
  428 + $groups[] = $group;
  429 + }
  430 + }
  431 + return $groups;
  432 + }
401 433
402 /** 434 /**
403 * Set stocks to override existing in product_stock table 435 * Set stocks to override existing in product_stock table
views/order/_form.php
@@ -146,8 +146,7 @@ JS; @@ -146,8 +146,7 @@ JS;
146 146
147 <?php $form = ActiveForm::begin( 147 <?php $form = ActiveForm::begin(
148 [ 148 [
149 - 'id' => 'main-form',  
150 -// 'options' => [ 'class' => 'form-inline' ], 149 + 'id' => 'main-form',
151 ] 150 ]
152 ); ?> 151 ); ?>
153 <div class="container"> 152 <div class="container">
@@ -333,7 +332,10 @@ JS; @@ -333,7 +332,10 @@ JS;
333 'id', 332 'id',
334 'short' 333 'short'
335 ), 334 ),
336 - [ 'prompt' => 'Способ оплаты ...' ] 335 + [
  336 + 'prompt' => 'Способ оплаты ...',
  337 + 'disabled' => $model->payment == 10 ? 'disabled' : false,
  338 + ]
337 ); ?> 339 ); ?>
338 340
339 <?= $form->field($model, 'insurance') ?> 341 <?= $form->field($model, 'insurance') ?>
@@ -368,348 +370,348 @@ JS; @@ -368,348 +370,348 @@ JS;
368 <br> 370 <br>
369 <br> 371 <br>
370 <div class="container"> 372 <div class="container">
371 - <div class="row">  
372 - <?php  
373 - echo GridView::widget(  
374 - [  
375 - 'dataProvider' => $dataProvider,  
376 - 'rowOptions' => function($model) {  
377 - if ($model->removed) {  
378 - return [ 'class' => 'danger' ];  
379 - } else {  
380 - return [];  
381 - }  
382 - },  
383 - 'layout' => '{items}{pager}',  
384 - 'columns' => [  
385 - [  
386 - 'class' => SerialColumn::className(),  
387 - ],  
388 - 'sku',  
389 - [  
390 - 'attribute' => 'product_name',  
391 - 'content' => function($model) {  
392 - if (!empty($model->product_name)) { 373 + <div class="row">
  374 + <?php
  375 + echo GridView::widget(
  376 + [
  377 + 'dataProvider' => $dataProvider,
  378 + 'rowOptions' => function ($model) {
  379 + if ($model->removed) {
  380 + return [ 'class' => 'danger' ];
  381 + } else {
  382 + return [];
  383 + }
  384 + },
  385 + 'layout' => '{items}{pager}',
  386 + 'columns' => [
  387 + [
  388 + 'class' => SerialColumn::className(),
  389 + ],
  390 + 'sku',
  391 + [
  392 + 'attribute' => 'product_name',
  393 + 'content' => function ($model) {
  394 + if (!empty( $model->product_name )) {
  395 +
  396 + if (empty( $model->productVariant )) {
  397 + return '';
  398 + }
  399 +
  400 + return Html::a(
  401 + StringHelper::truncate($model->product_name, 10, '...'),
  402 + '#',
  403 + [
  404 + 'onclick' => 'event.preventDefault();',
  405 + 'data-toggle' => 'popover',
  406 + 'data-placement' => 'right',
  407 + 'data-html' => 'true',
  408 + 'data-content' => Html::img(
  409 + $model->productVariant->imageUrl,
  410 + [
  411 + 'class' => 'img-rounded',
  412 + ]
  413 + ) . Html::tag('p', $model->product_name),
  414 + ]
  415 + );
  416 + } else {
  417 + return '';
  418 + }
  419 + },
  420 + ],
  421 + [
  422 + 'attribute' => 'productVariant.product.brand.lang.title',
  423 + 'label' => 'Брэнд',
  424 + ],
  425 + [
  426 + 'attribute' => 'productVariant.lang.title',
  427 + 'label' => \Yii::t('app', 'Цвет'),
  428 + 'content' => function ($model) {
393 429
394 - if (empty($model->productVariant)) { 430 + if (empty( $model->productVariant )) {
395 return ''; 431 return '';
396 - }  
397 -  
398 - return Html::a(  
399 - StringHelper::truncate($model->product_name, 10, '...'),  
400 - '#',  
401 - [  
402 - 'onclick' => 'event.preventDefault();',  
403 - 'data-toggle' => 'popover',  
404 - 'data-placement' => 'right',  
405 - 'data-html' => 'true',  
406 - 'data-content' => Html::img(  
407 - $model->productVariant->imageUrl,  
408 - [  
409 - 'class' => 'img-rounded',  
410 - ]  
411 - ) . Html::tag('p', $model->product_name),  
412 - ]  
413 - );  
414 - } else {  
415 - return '';  
416 - }  
417 - },  
418 - ],  
419 - [  
420 - 'attribute' => 'productVariant.product.brand.lang.title',  
421 - 'label' => 'Брэнд',  
422 - ],  
423 - [  
424 - 'attribute' => 'productVariant.lang.title',  
425 - 'label' => \Yii::t('app', 'Цвет'),  
426 - 'content' => function($model) {  
427 -  
428 - if (empty($model->productVariant)) {  
429 - return '';  
430 - }  
431 -  
432 - if (preg_match('@.*\.(png|jpg|gif)@i', $model->productVariant->lang->title)) {  
433 - return '';  
434 - } else {  
435 - return $model->productVariant->lang->title;  
436 - }  
437 - },  
438 - ],  
439 - [  
440 - 'attribute' => 'productVariant.size',  
441 - 'label' => 'Размер',  
442 - ],  
443 - 'price',  
444 - [  
445 - 'class' => 'kartik\grid\EditableColumn',  
446 - 'attribute' => 'count',  
447 - 'editableOptions' => [  
448 - 'header' => \Yii::t('app', 'Количество'),  
449 - 'inputType' => kartik\editable\Editable::INPUT_SPIN,  
450 - 'options' => [  
451 - 'pluginOptions' => [  
452 - 'min' => 0,  
453 - 'max' => 5000,  
454 - ],  
455 - ],  
456 - 'pluginEvents' => [  
457 - 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',  
458 - ],  
459 - ],  
460 - 'format' => [  
461 - 'decimal',  
462 - 0,  
463 - ],  
464 - 'pageSummary' => false,  
465 - ],  
466 - 'sum_cost',  
467 - [  
468 - 'class' => 'kartik\grid\EditableColumn',  
469 - 'attribute' => 'booking',  
470 - 'editableOptions' => [  
471 - 'header' => \Yii::t('app', 'Бронь'),  
472 - 'inputType' => kartik\editable\Editable::INPUT_TEXT,  
473 - 'options' => [  
474 - 'class' => 'booking-typeahead',  
475 - 'pluginOptions' => [  
476 - 'min' => 0,  
477 - 'max' => 20,  
478 - ],  
479 - ],  
480 - 'pluginEvents' => [  
481 - 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',  
482 - ],  
483 - ],  
484 - 'format' => [  
485 - 'text',  
486 - ],  
487 - 'pageSummary' => false,  
488 - ],  
489 - [  
490 - 'class' => 'kartik\grid\EditableColumn',  
491 - 'attribute' => 'status',  
492 - 'editableOptions' => [  
493 - 'header' => \Yii::t('app', 'Статус'),  
494 - 'inputType' => kartik\editable\Editable::INPUT_TEXT,  
495 - 'options' => [  
496 - 'class' => 'status-typeahead',  
497 - 'pluginOptions' => [  
498 - 'min' => 0,  
499 - 'max' => 20,  
500 - ],  
501 - ],  
502 - 'pluginEvents' => [  
503 - 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',  
504 - ],  
505 - ],  
506 - 'format' => [  
507 - 'text',  
508 - ],  
509 - 'pageSummary' => false,  
510 - ],  
511 - [  
512 - 'class' => 'kartik\grid\EditableColumn',  
513 - 'attribute' => 'return',  
514 - 'editableOptions' => [  
515 - 'header' => \Yii::t('app', 'Возврат'),  
516 - 'inputType' => kartik\editable\Editable::INPUT_CHECKBOX,  
517 - 'options' => [],  
518 - 'pluginEvents' => [  
519 - 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',  
520 - ],  
521 - ],  
522 - 'format' => [  
523 - 'boolean',  
524 - ],  
525 - 'pageSummary' => false,  
526 - ],  
527 - [  
528 - 'content' => function($model) {  
529 -  
530 - if (empty($model->productVariant)) {  
531 - return '<i class="glyphicon glyphicon-remove"></i>';  
532 - }  
533 -  
534 - $content = '<table class="table"><tbody><tr><th>Склад</th><th>кол.</th></tr>';  
535 - foreach ($model->productVariant->variantStocks as $stock) {  
536 - $content .= '<tr><td>' . $stock->stock->title . '</td><td>' . $stock->quantity . '</td></tr>';  
537 - }  
538 - return Html::a(  
539 - '<i class="glyphicon glyphicon-home"></i>',  
540 - '#',  
541 - [  
542 - 'onclick' => 'event.preventDefault();',  
543 - 'data-toggle' => 'popover',  
544 - 'data-placement' => 'left',  
545 - 'data-html' => 'true',  
546 - 'data-content' => $content . '</tbody></table>',  
547 - ]  
548 - );  
549 - },  
550 - ],  
551 - [  
552 - 'class' => 'yii\grid\ActionColumn',  
553 - 'template' => '{delete}',  
554 - 'buttons' => [  
555 - 'delete' => function($url, $product) {  
556 - if ($product->removed) {  
557 - return '';  
558 - } else {  
559 - return Html::a(  
560 - Html::tag('span', '', [ 'class' => 'glyphicon glyphicon-trash' ]),  
561 - [  
562 - 'delete-product',  
563 - 'id' => $product->id,  
564 - ],  
565 - [  
566 - 'class' => 'delete-button',  
567 - // 'data' => [  
568 - // 'confirm' => 'Вы уверены, что хотите удалить этот элемент?',  
569 - // 'method' => 'GET',  
570 - // ],  
571 - ]  
572 - );  
573 - }  
574 - },  
575 - ],  
576 - ],  
577 - ],  
578 - 'responsive' => true,  
579 - 'hover' => true,  
580 - 'pjax' => true,  
581 - 'pjaxSettings' => [  
582 - 'options' => [  
583 - 'scrollTo' => 'false',  
584 - 'id' => 'order-products-grid',  
585 - ],  
586 - ],  
587 - ]  
588 - );  
589 - ?>  
590 - </div> 432 + }
  433 +
  434 + if (preg_match('@.*\.(png|jpg|gif)@i', $model->productVariant->lang->title)) {
  435 + return '';
  436 + } else {
  437 + return $model->productVariant->lang->title;
  438 + }
  439 + },
  440 + ],
  441 + [
  442 + 'attribute' => 'productVariant.size',
  443 + 'label' => 'Размер',
  444 + ],
  445 + 'price',
  446 + [
  447 + 'class' => 'kartik\grid\EditableColumn',
  448 + 'attribute' => 'count',
  449 + 'editableOptions' => [
  450 + 'header' => \Yii::t('app', 'Количество'),
  451 + 'inputType' => kartik\editable\Editable::INPUT_SPIN,
  452 + 'options' => [
  453 + 'pluginOptions' => [
  454 + 'min' => 0,
  455 + 'max' => 5000,
  456 + ],
  457 + ],
  458 + 'pluginEvents' => [
  459 + 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',
  460 + ],
  461 + ],
  462 + 'format' => [
  463 + 'decimal',
  464 + 0,
  465 + ],
  466 + 'pageSummary' => false,
  467 + ],
  468 + 'sum_cost',
  469 + [
  470 + 'class' => 'kartik\grid\EditableColumn',
  471 + 'attribute' => 'booking',
  472 + 'editableOptions' => [
  473 + 'header' => \Yii::t('app', 'Бронь'),
  474 + 'inputType' => kartik\editable\Editable::INPUT_TEXT,
  475 + 'options' => [
  476 + 'class' => 'booking-typeahead',
  477 + 'pluginOptions' => [
  478 + 'min' => 0,
  479 + 'max' => 20,
  480 + ],
  481 + ],
  482 + 'pluginEvents' => [
  483 + 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',
  484 + ],
  485 + ],
  486 + 'format' => [
  487 + 'text',
  488 + ],
  489 + 'pageSummary' => false,
  490 + ],
  491 + [
  492 + 'class' => 'kartik\grid\EditableColumn',
  493 + 'attribute' => 'status',
  494 + 'editableOptions' => [
  495 + 'header' => \Yii::t('app', 'Статус'),
  496 + 'inputType' => kartik\editable\Editable::INPUT_TEXT,
  497 + 'options' => [
  498 + 'class' => 'status-typeahead',
  499 + 'pluginOptions' => [
  500 + 'min' => 0,
  501 + 'max' => 20,
  502 + ],
  503 + ],
  504 + 'pluginEvents' => [
  505 + 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',
  506 + ],
  507 + ],
  508 + 'format' => [
  509 + 'text',
  510 + ],
  511 + 'pageSummary' => false,
  512 + ],
  513 + [
  514 + 'class' => 'kartik\grid\EditableColumn',
  515 + 'attribute' => 'return',
  516 + 'editableOptions' => [
  517 + 'header' => \Yii::t('app', 'Возврат'),
  518 + 'inputType' => kartik\editable\Editable::INPUT_CHECKBOX,
  519 + 'options' => [],
  520 + 'pluginEvents' => [
  521 + 'editableSuccess' => 'function(event) { $.pjax.reload({container:"#order-products-grid"}); }',
  522 + ],
  523 + ],
  524 + 'format' => [
  525 + 'boolean',
  526 + ],
  527 + 'pageSummary' => false,
  528 + ],
  529 + [
  530 + 'content' => function ($model) {
  531 +
  532 + if (empty( $model->productVariant )) {
  533 + return '<i class="glyphicon glyphicon-remove"></i>';
  534 + }
  535 +
  536 + $content = '<table class="table"><tbody><tr><th>Склад</th><th>кол.</th></tr>';
  537 + foreach ($model->productVariant->variantStocks as $stock) {
  538 + $content .= '<tr><td>' . $stock->stock->title . '</td><td>' . $stock->quantity . '</td></tr>';
  539 + }
  540 + return Html::a(
  541 + '<i class="glyphicon glyphicon-home"></i>',
  542 + '#',
  543 + [
  544 + 'onclick' => 'event.preventDefault();',
  545 + 'data-toggle' => 'popover',
  546 + 'data-placement' => 'left',
  547 + 'data-html' => 'true',
  548 + 'data-content' => $content . '</tbody></table>',
  549 + ]
  550 + );
  551 + },
  552 + ],
  553 + [
  554 + 'class' => 'yii\grid\ActionColumn',
  555 + 'template' => '{delete}',
  556 + 'buttons' => [
  557 + 'delete' => function ($url, $product) {
  558 + if ($product->removed) {
  559 + return '';
  560 + } else {
  561 + return Html::a(
  562 + Html::tag('span', '', [ 'class' => 'glyphicon glyphicon-trash' ]),
  563 + [
  564 + 'delete-product',
  565 + 'id' => $product->id,
  566 + ],
  567 + [
  568 + 'class' => 'delete-button',
  569 + // 'data' => [
  570 + // 'confirm' => 'Вы уверены, что хотите удалить этот элемент?',
  571 + // 'method' => 'GET',
  572 + // ],
  573 + ]
  574 + );
  575 + }
  576 + },
  577 + ],
  578 + ],
  579 + ],
  580 + 'responsive' => true,
  581 + 'hover' => true,
  582 + 'pjax' => true,
  583 + 'pjaxSettings' => [
  584 + 'options' => [
  585 + 'scrollTo' => 'false',
  586 + 'id' => 'order-products-grid',
  587 + ],
  588 + ],
  589 + ]
  590 + );
  591 + ?>
  592 + </div>
591 </div> 593 </div>
592 <div class="container"> 594 <div class="container">
593 <?php Pjax::begin([ 'id' => 'total-cost' ]); ?> 595 <?php Pjax::begin([ 'id' => 'total-cost' ]); ?>
594 - <h2>Сумма заказа : <span class="label label-success"><?php echo $model->total; ?><?php echo \Yii::t(  
595 - 'app',  
596 - 'грн'  
597 - ) ?></span></h2> 596 + <h2>Сумма заказа : <span class="label label-success"><?php echo $model->total; ?><?php echo \Yii::t(
  597 + 'app',
  598 + 'грн'
  599 + ) ?></span></h2>
598 <?php Pjax::end(); ?> 600 <?php Pjax::end(); ?>
599 </div> 601 </div>
600 <div class="container"> 602 <div class="container">
601 - <div class="row">  
602 - <?php $newProductForm = ActiveForm::begin(  
603 - [  
604 - 'action' => yii\helpers\Url::to([ 'add' ]),  
605 - 'id' => 'add-product-form',  
606 - ]  
607 - );  
608 - $newOrderProduct = new OrderProduct();  
609 - ?>  
610 - <div class="col-md-8">  
611 - <?php echo $newProductForm->field($newOrderProduct, 'id')  
612 - ->widget(  
613 - Select2::className(),  
614 - [  
615 - 'options' => [ 'placeholder' => 'Search for a product ...' ],  
616 - 'pluginOptions' => [  
617 - 'allowClear' => true,  
618 - 'disabled' => $model->isNewRecord ? true : false,  
619 - 'minimumInputLength' => 3,  
620 - 'language' => [  
621 - 'errorLoading' => new JsExpression(  
622 - "function () { return 'Waiting for results...'; }" 603 + <div class="row">
  604 + <?php $newProductForm = ActiveForm::begin(
  605 + [
  606 + 'action' => yii\helpers\Url::to([ 'add' ]),
  607 + 'id' => 'add-product-form',
  608 + ]
  609 + );
  610 + $newOrderProduct = new OrderProduct();
  611 + ?>
  612 + <div class="col-md-8">
  613 + <?php echo $newProductForm->field($newOrderProduct, 'id')
  614 + ->widget(
  615 + Select2::className(),
  616 + [
  617 + 'options' => [ 'placeholder' => 'Search for a product ...' ],
  618 + 'pluginOptions' => [
  619 + 'allowClear' => true,
  620 + 'disabled' => $model->isNewRecord ? true : false,
  621 + 'minimumInputLength' => 3,
  622 + 'language' => [
  623 + 'errorLoading' => new JsExpression(
  624 + "function () { return 'Waiting for results...'; }"
  625 + ),
  626 + ],
  627 + 'ajax' => [
  628 + 'url' => \yii\helpers\Url::to([ 'find-product' ]),
  629 + 'dataType' => 'json',
  630 + 'data' => new JsExpression(
  631 + 'function(params) { return {q:params.term}; }'
  632 + ),
  633 + ],
  634 + 'escapeMarkup' => new JsExpression(
  635 + 'function (markup) { return markup; }'
623 ), 636 ),
624 - ],  
625 - 'ajax' => [  
626 - 'url' => \yii\helpers\Url::to([ 'find-product' ]),  
627 - 'dataType' => 'json',  
628 - 'data' => new JsExpression(  
629 - 'function(params) { return {q:params.term}; }' 637 + 'templateResult' => new JsExpression(
  638 + 'function(data) { return data.sku; }'
  639 + ),
  640 + 'templateSelection' => new JsExpression(
  641 + 'function (data) { return data.sku; }'
630 ), 642 ),
631 ], 643 ],
632 - 'escapeMarkup' => new JsExpression(  
633 - 'function (markup) { return markup; }'  
634 - ),  
635 - 'templateResult' => new JsExpression(  
636 - 'function(data) { return data.sku; }'  
637 - ),  
638 - 'templateSelection' => new JsExpression(  
639 - 'function (data) { return data.sku; }'  
640 - ),  
641 - ],  
642 - ]  
643 - )  
644 - ->label('Артикул');  
645 -  
646 - ?>  
647 - </div>  
648 - <div class="col-md-2">  
649 - <?php echo $newProductForm->field(  
650 - $newOrderProduct,  
651 - 'count'  
652 - )  
653 - ->input(  
654 - 'number', 644 + ]
  645 + )
  646 + ->label('Артикул');
  647 +
  648 + ?>
  649 + </div>
  650 + <div class="col-md-2">
  651 + <?php echo $newProductForm->field(
  652 + $newOrderProduct,
  653 + 'count'
  654 + )
  655 + ->input(
  656 + 'number',
  657 + [
  658 + 'disabled' => $model->isNewRecord ? true : false,
  659 + ]
  660 + ); ?>
  661 + </div>
  662 + <div class="col-md-2" style="margin-top: 23px">
  663 + <?php echo Html::submitButton(
  664 + \Yii::t('app', 'Добавить'),
  665 + [
  666 + 'class' => $model->isNewRecord ? 'btn btn-primary disabled' : 'btn btn-primary',
  667 + ]
  668 + ) ?>
  669 + </div>
  670 + <?php echo $newProductForm->field($newOrderProduct, 'order_id')
  671 + ->hiddenInput(
655 [ 672 [
656 - 'disabled' => $model->isNewRecord ? true : false, 673 + 'value' => $model->id,
657 ] 674 ]
658 - ); ?> 675 + )
  676 + ->label(false) ?>
  677 + <?php ActiveForm::end(); ?>
659 </div> 678 </div>
660 - <div class="col-md-2" style="margin-top: 23px">  
661 - <?php echo Html::submitButton(  
662 - \Yii::t('app', 'Добавить'), 679 +
  680 + <br>
  681 + <div class="row">
  682 + <?= Html::button(
  683 + $model->isNewRecord ? \Yii::t('app', 'Создать') : \Yii::t('app', 'Сохранить'),
  684 + [
  685 + 'class' => $model->isNewRecord ? 'btn btn-success btn-lg' : 'btn btn-primary btn-lg',
  686 + 'id' => 'page-submit',
  687 + ]
  688 + ) ?>
  689 + <?= Html::a(
  690 + \Yii::t('app', 'Печать'),
  691 + yii\helpers\Url::to(
  692 + [
  693 + 'order/print',
  694 + 'order_id' => $model->id,
  695 + ]
  696 + ),
  697 + [
  698 + 'class' => $model->isNewRecord ? 'btn btn-info disabled btn-lg' : 'btn btn-info btn-lg',
  699 + 'target' => '_blank',
  700 + ]
  701 + ) ?>
  702 + <?= Html::a(
  703 + \Yii::t('app', 'Выйти'),
  704 + yii\helpers\Url::to(
  705 + [
  706 + 'close-order',
  707 + 'id' => $model->id,
  708 + ]
  709 + ),
663 [ 710 [
664 - 'class' => $model->isNewRecord ? 'btn btn-primary disabled' : 'btn btn-primary', 711 + 'class' => $model->isNewRecord ? 'btn btn-info disabled btn-lg' : 'btn btn-info btn-lg',
665 ] 712 ]
666 ) ?> 713 ) ?>
667 </div> 714 </div>
668 - <?php echo $newProductForm->field($newOrderProduct, 'order_id')  
669 - ->hiddenInput(  
670 - [  
671 - 'value' => $model->id,  
672 - ]  
673 - )  
674 - ->label(false) ?>  
675 - <?php ActiveForm::end(); ?>  
676 - </div>  
677 -  
678 - <br>  
679 - <div class="row">  
680 - <?= Html::button(  
681 - $model->isNewRecord ? \Yii::t('app', 'Создать') : \Yii::t('app', 'Сохранить'),  
682 - [  
683 - 'class' => $model->isNewRecord ? 'btn btn-success btn-lg' : 'btn btn-primary btn-lg',  
684 - 'id' => 'page-submit',  
685 - ]  
686 - ) ?>  
687 - <?= Html::a(  
688 - \Yii::t('app', 'Печать'),  
689 - yii\helpers\Url::to(  
690 - [  
691 - 'order/print',  
692 - 'order_id' => $model->id,  
693 - ]  
694 - ),  
695 - [  
696 - 'class' => $model->isNewRecord ? 'btn btn-info disabled btn-lg' : 'btn btn-info btn-lg',  
697 - 'target' => '_blank',  
698 - ]  
699 - ) ?>  
700 - <?= Html::a(  
701 - \Yii::t('app', 'Выйти'),  
702 - yii\helpers\Url::to(  
703 - [  
704 - 'close-order',  
705 - 'id' => $model->id,  
706 - ]  
707 - ),  
708 - [  
709 - 'class' => $model->isNewRecord ? 'btn btn-info disabled btn-lg' : 'btn btn-info btn-lg',  
710 - ]  
711 - ) ?>  
712 - </div>  
713 715
714 </div> 716 </div>
715 <br> 717 <br>
views/order/_log_item.php 0 → 100644
  1 +<?php
  2 + /**
  3 + * @var OrderLog $model
  4 + * @var Order $order
  5 + */
  6 + use artweb\artbox\ecommerce\models\Order;
  7 + use artweb\artbox\ecommerce\models\OrderLog;
  8 + use yii\helpers\Html;
  9 + use yii\helpers\Json;
  10 +
  11 +?>
  12 +
  13 +<!-- timeline item -->
  14 +<li>
  15 + <!-- timeline icon -->
  16 + <i class="fa fa-user bg-orange"></i>
  17 + <div class="timeline-item">
  18 + <span class="time"><i class="fa fa-calendar"></i> <?= Yii::$app->formatter->asDatetime($model->created_at) ?></span>
  19 +
  20 + <h3 class="timeline-header">Пользователь: <span class="text-orange"><?= $model->user->username ?></span></h3>
  21 +
  22 + <div class="timeline-body">
  23 + <table class="table table-bordered table-striped">
  24 + <tr>
  25 + <th>Поле</th>
  26 + <th>Старое значение</th>
  27 + <th>Новое значение</th>
  28 + </tr>
  29 + <?php
  30 + foreach (Json::decode($model->data) as $key => $item) {
  31 + echo Html::tag(
  32 + 'tr',
  33 + Html::tag('td', $order->attributeLabels()[ $key ]) . Html::tag('td', $item[ 'old' ]) . Html::tag(
  34 + 'td',
  35 + $item[ 'new' ]
  36 + )
  37 + );
  38 + }
  39 + ?>
  40 + </table>
  41 + </div>
  42 +
  43 + </div>
  44 +</li>
views/order/_timeline_item.php 0 → 100644
  1 +<?php
  2 + /**
  3 + * @var OrderLabelHistory $model
  4 + */
  5 + use artweb\artbox\ecommerce\models\OrderLabelHistory;
  6 + use yii\helpers\Html;
  7 +
  8 +?>
  9 +
  10 +<!-- timeline item -->
  11 +<li>
  12 + <!-- timeline icon -->
  13 + <i class="fa fa-tag bg-blue"></i>
  14 + <div class="timeline-item">
  15 + <span class="time"><i class="fa fa-calendar"></i> <?=Yii::$app->formatter->asDatetime($model->created_at)?></span>
  16 +
  17 + <h3 class="timeline-header"><?=$model->label->lang->title?></h3>
  18 +
  19 + <div class="timeline-body">
  20 + <?php
  21 + if (empty($model->user)) {
  22 + echo Html::tag('p', 'Поступил с сайта', ['class' => 'text-green']);
  23 + } else {
  24 + echo 'Статус присвоил: ' . Html::tag('p', $model->user->username, [
  25 + 'class' => 'text-blue'
  26 + ]);
  27 + }
  28 + ?>
  29 + </div>
  30 +
  31 + </div>
  32 +</li>
views/order/index.php
@@ -347,7 +347,7 @@ JS; @@ -347,7 +347,7 @@ JS;
347 [ 347 [
348 'class' => 'yii\grid\ActionColumn', 348 'class' => 'yii\grid\ActionColumn',
349 'template' => \Yii::$app->user->identity->isAdmin( 349 'template' => \Yii::$app->user->identity->isAdmin(
350 - ) ? '{view} {update} {delete}' : '{view} {update}', 350 + ) ? '{history} {view} {update} {delete}' : '{view} {update}',
351 'buttons' => [ 351 'buttons' => [
352 'update' => function($url, $model) { 352 'update' => function($url, $model) {
353 return Html::a( 353 return Html::a(
@@ -359,6 +359,16 @@ JS; @@ -359,6 +359,16 @@ JS;
359 ] 359 ]
360 ); 360 );
361 }, 361 },
  362 + 'history' => function($url, $model) {
  363 + return Html::a(
  364 + Html::tag('span', '', [ 'class' => 'glyphicon glyphicon-time' ]),
  365 + ['log', 'id' => $model->id],
  366 + [
  367 + 'target' => '_blank',
  368 + 'data-pjax' => '0',
  369 + ]
  370 + );
  371 + },
362 ], 372 ],
363 ], 373 ],
364 ], 374 ],
views/order/log.php 0 → 100755
  1 +<?php
  2 + use artweb\artbox\ecommerce\models\Order;
  3 + use yii\data\ActiveDataProvider;
  4 + use yii\web\View;
  5 + use yii\widgets\ListView;
  6 +
  7 + /**
  8 + * @var View $this
  9 + * @var ActiveDataProvider $logData
  10 + * @var Order $model
  11 + */
  12 +
  13 + $this->title = 'История заказа #' . $model->id;
  14 +
  15 + $this->params[ 'breadcrumbs' ][] = [
  16 + 'url' => yii\helpers\Url::to([ '/ecommerce/order/index' ]),
  17 + 'label' => \Yii::t('app', 'Заказы'),
  18 + ];
  19 + $this->params[ 'breadcrumbs' ][] = [
  20 + 'url' => yii\helpers\Url::to([ '/ecommerce/order/view', 'id' => $model->id ]),
  21 + 'label' => \Yii::t('app', 'Заказ #') . $model->id,
  22 + ];
  23 + $this->params[ 'breadcrumbs' ][] = $this->title;
  24 +
  25 +?>
  26 +
  27 +<div class="order-log">
  28 + <div class="box box-default">
  29 + <div class="box-header with-border">
  30 + <h3 class="box-title">История</h3>
  31 + <div class="box-body">
  32 +
  33 + <?php
  34 + echo ListView::widget(
  35 + [
  36 + 'dataProvider' => $logData,
  37 + 'layout' => '{items}',
  38 + 'itemView' => '_log_item',
  39 + 'itemOptions' => [
  40 + 'tag' => false,
  41 + ],
  42 + 'options' => [
  43 + 'tag' => $logData->totalCount == 0 ? 'div' : 'ul',
  44 + 'class' => $logData->totalCount == 0 ? 'list-view' : 'list-view timeline',
  45 + ],
  46 + 'viewParams' => [
  47 + 'order' => $model,
  48 + ],
  49 + 'emptyText' => 'У этого заказа пока нет истории',
  50 + 'emptyTextOptions' => [
  51 + 'class' => 'callout callout-info'
  52 + ],
  53 + ]
  54 + );
  55 + ?>
  56 +
  57 + </div><!-- /.box-body -->
  58 + </div><!-- /.box -->
  59 + </div>
views/order/update.php
@@ -10,11 +10,15 @@ @@ -10,11 +10,15 @@
10 use yii\helpers\Html; 10 use yii\helpers\Html;
11 use yii\web\View; 11 use yii\web\View;
12 12
13 - $this->title = 'Заказ #' . $model->id; 13 + $this->title = 'Обновить заказ #' . $model->id;
14 $this->params[ 'breadcrumbs' ][] = [ 14 $this->params[ 'breadcrumbs' ][] = [
15 'url' => yii\helpers\Url::to([ '/ecommerce/order/index' ]), 15 'url' => yii\helpers\Url::to([ '/ecommerce/order/index' ]),
16 'label' => \Yii::t('app', 'Заказы'), 16 'label' => \Yii::t('app', 'Заказы'),
17 ]; 17 ];
  18 + $this->params[ 'breadcrumbs' ][] = [
  19 + 'url' => yii\helpers\Url::to([ '/ecommerce/order/view', 'id' => $model->id, ]),
  20 + 'label' => \Yii::t('app', 'Заказ #') . $model->id,
  21 + ];
18 $this->params[ 'breadcrumbs' ][] = $this->title; 22 $this->params[ 'breadcrumbs' ][] = $this->title;
19 23
20 $js = ' 24 $js = '
@@ -54,7 +58,18 @@ $.ajax({ @@ -54,7 +58,18 @@ $.ajax({
54 '; 58 ';
55 59
56 $this->registerJs($js, View::POS_READY); 60 $this->registerJs($js, View::POS_READY);
57 - 61 +
  62 + if (!empty(\Yii::$app->session->getFlash('label_update'))) {
  63 + $js = '
  64 +$.notify({
  65 + message: "Статус заказа обновлен"
  66 +}, {
  67 + type : "warning"
  68 +})
  69 +';
  70 + $this->registerJs($js, View::POS_READY);
  71 + }
  72 +
58 ?> 73 ?>
59 <div class="order-update"> 74 <div class="order-update">
60 <div class="container"> 75 <div class="container">
views/order/view.php
1 <?php 1 <?php
2 2
3 use artweb\artbox\ecommerce\models\Order; 3 use artweb\artbox\ecommerce\models\Order;
  4 + use common\components\CreditHelper;
4 use kartik\grid\GridView; 5 use kartik\grid\GridView;
  6 + use yii\data\ActiveDataProvider;
  7 + use yii\grid\SerialColumn;
5 use yii\helpers\Html; 8 use yii\helpers\Html;
6 use yii\web\View; 9 use yii\web\View;
7 use yii\widgets\DetailView; 10 use yii\widgets\DetailView;
  11 + use yii\widgets\ListView;
8 12
9 /** 13 /**
10 - * @var View $this  
11 - * @var Order $model 14 + * @var View $this
  15 + * @var Order $model
  16 + * @var ActiveDataProvider $products
  17 + * @var ActiveDataProvider $historyData
12 */ 18 */
13 19
14 $this->title = 'Заказ #' . $model->id; 20 $this->title = 'Заказ #' . $model->id;
@@ -17,65 +23,184 @@ @@ -17,65 +23,184 @@
17 'url' => [ 'index' ], 23 'url' => [ 'index' ],
18 ]; 24 ];
19 $this->params[ 'breadcrumbs' ][] = $this->title; 25 $this->params[ 'breadcrumbs' ][] = $this->title;
  26 +
  27 + if (empty($model->payment)) {
  28 + $payment = '';
  29 + } elseif ($model->payment == 10) {
  30 + $payment = Html::tag('h4', $model->orderPayment->lang->title, [ 'class' => 'text-navy' ]) . Html::beginTag(
  31 + 'table',
  32 + [ 'class' => 'table table-bordered' ]
  33 + ) . Html::tag(
  34 + 'tr',
  35 + Html::tag('td', $model->getAttributeLabel('credit_sum')) . Html::tag(
  36 + 'td',
  37 + CreditHelper::checkSum(
  38 + $model->credit_sum
  39 + )
  40 + )
  41 + ) . Html::tag(
  42 + 'tr',
  43 + Html::tag('td', $model->getAttributeLabel('credit_month')) . Html::tag(
  44 + 'td',
  45 + CreditHelper::checkMonth(
  46 + $model->credit_month
  47 + )
  48 + )
  49 + ) . Html::tag(
  50 + 'tr',
  51 + Html::tag('td', 'Кредит') . Html::tag('td', $model->total - $model->credit_sum)
  52 + ) . Html::tag(
  53 + 'tr',
  54 + Html::tag('td', 'Оплата в месяц') . Html::tag(
  55 + 'td',
  56 + CreditHelper::getCredit(
  57 + $model->total - $model->credit_sum,
  58 + $model->credit_month
  59 + ) . ' грн/мес'
  60 + )
  61 + ) . Html::endTag('table');
  62 + } else {
  63 + $payment = $model->orderPayment->lang->title;
  64 + }
  65 +
20 ?> 66 ?>
21 <div class="order-view"> 67 <div class="order-view">
22 -  
23 - <h1><?= Html::encode($this->title) ?></h1>  
24 -  
25 - <p>  
26 - <?= Html::a(  
27 - 'Update',  
28 - [  
29 - 'update',  
30 - 'id' => $model->id,  
31 - ],  
32 - [ 'class' => 'btn btn-primary' ]  
33 - ) ?>  
34 -  
35 - </p>  
36 -  
37 - <?= DetailView::widget(  
38 - [  
39 - 'model' => $model,  
40 - 'attributes' => [  
41 - 'id',  
42 - 'deadline',  
43 - 'pay',  
44 - 'reason',  
45 - 'label',  
46 - 'name',  
47 - 'phone',  
48 - 'email',  
49 - 'comment',  
50 - 'delivery',  
51 - 'declaration',  
52 - 'stock',  
53 - 'payment',  
54 - 'insurance',  
55 - 'city',  
56 - 'adress',  
57 - 'body',  
58 - 'check',  
59 - 'sms',  
60 - ],  
61 - ]  
62 - ) ?>  
63 -  
64 - <?php  
65 - echo GridView::widget( 68 +
  69 + <h1><?= Html::encode($this->title) ?></h1>
  70 +
  71 + <p>
  72 + <?= Html::a(
  73 + 'Обновить',
  74 + [
  75 + 'update',
  76 + 'id' => $model->id,
  77 + ],
  78 + [ 'class' => 'btn btn-primary' ]
  79 + ) ?>
  80 +
  81 + <?= Html::a(
  82 + 'История',
  83 + [
  84 + 'log',
  85 + 'id' => $model->id,
  86 + ],
  87 + [ 'class' => 'btn bg-orange' ]
  88 + ) ?>
  89 + </p>
  90 +
  91 + <div class="box box-default">
  92 + <div class="box-header with-border">
  93 + <h3 class="box-title">Данные заказа</h3>
  94 + <div class="box-tools pull-right">
  95 + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
  96 + </div><!-- /.box-tools -->
  97 + </div><!-- /.box-header -->
  98 + <div class="box-body">
  99 + <?= DetailView::widget(
66 [ 100 [
67 - 'dataProvider' => $products,  
68 - 'columns' => [ 101 + 'model' => $model,
  102 + 'attributes' => [
69 'id', 103 'id',
70 - 'product_name', 104 + 'deadline',
  105 + 'pay',
  106 + [
  107 + 'label' => 'Причина',
  108 + 'value' => empty($model->reason) ? '' : Order::REASONS[ $model->reason ],
  109 + ],
  110 + [
  111 + 'label' => 'Статус',
  112 + 'value' => empty($model->label) ? '' : $model->orderLabel->lang->title,
  113 + ],
71 'name', 114 'name',
72 - 'sku',  
73 - 'price',  
74 - 'count',  
75 - 'sum_cost', 115 + 'phone',
  116 + 'email',
  117 + 'comment',
  118 + [
  119 + 'label' => 'Способ доставки',
  120 + 'value' => empty($model->delivery) ? '' : $model->orderDelivery->lang->title,
  121 + ],
  122 + 'declaration',
  123 + 'stock',
  124 + [
  125 + 'label' => 'Способ оплаты',
  126 + 'value' => $payment,
  127 + 'format' => 'html',
  128 + ],
  129 + 'insurance',
  130 + 'city',
  131 + 'adress',
  132 + 'body',
  133 + 'check',
  134 + 'sms',
76 ], 135 ],
77 ] 136 ]
78 - );  
79 - ?> 137 + ) ?>
  138 + </div><!-- /.box-body -->
  139 + </div><!-- /.box -->
  140 +
  141 +
  142 + <div class="box box-default">
  143 + <div class="box-header with-border">
  144 + <h3 class="box-title">Товары</h3>
  145 + <div class="box-tools pull-right">
  146 + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
  147 + </div><!-- /.box-tools -->
  148 + </div><!-- /.box-header -->
  149 + <div class="box-body">
  150 + <?php
  151 + echo GridView::widget(
  152 + [
  153 + 'dataProvider' => $products,
  154 + 'columns' => [
  155 + [
  156 + 'class' => SerialColumn::className(),
  157 + ],
  158 + 'product_name',
  159 + 'name',
  160 + 'sku',
  161 + 'price',
  162 + 'count',
  163 + 'sum_cost',
  164 + ],
  165 + ]
  166 + );
  167 + ?>
  168 + </div><!-- /.box-body -->
  169 + </div><!-- /.box -->
  170 +
  171 + <div class="box box-default">
  172 + <div class="box-header with-border">
  173 + <h3 class="box-title">История</h3>
  174 + <div class="box-tools pull-right">
  175 + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
  176 + </div><!-- /.box-tools -->
  177 + </div><!-- /.box-header -->
  178 + <div class="box-body">
  179 +
  180 +
  181 + <?php
  182 + echo ListView::widget(
  183 + [
  184 + 'dataProvider' => $historyData,
  185 + 'layout' => '{items}',
  186 + 'itemView' => '_timeline_item',
  187 + 'itemOptions' => [
  188 + 'tag' => false,
  189 + ],
  190 + 'options' => [
  191 + 'tag' => $historyData->totalCount == 0 ? 'div' : 'ul',
  192 + 'class' => $historyData->totalCount == 0 ? 'list-view' : 'list-view timeline',
  193 + ],
  194 + 'emptyText' => 'У этого заказа пока нет истории',
  195 + 'emptyTextOptions' => [
  196 + 'class' => 'callout callout-info',
  197 + ],
  198 + ]
  199 + );
  200 + ?>
  201 +
  202 +
  203 + </div><!-- /.box-body -->
  204 + </div><!-- /.box -->
80 205
81 </div> 206 </div>
views/statistics/index.php
1 <?php 1 <?php
2 use artweb\artbox\ecommerce\models\Label; 2 use artweb\artbox\ecommerce\models\Label;
3 use artweb\artbox\ecommerce\models\Order; 3 use artweb\artbox\ecommerce\models\Order;
  4 + use artweb\artbox\ecommerce\models\ProductVariant;
  5 + use common\models\User;
4 use kartik\daterange\DateRangePicker; 6 use kartik\daterange\DateRangePicker;
5 use kartik\grid\GridView; 7 use kartik\grid\GridView;
6 use kartik\select2\Select2; 8 use kartik\select2\Select2;
@@ -14,19 +16,30 @@ @@ -14,19 +16,30 @@
14 /** 16 /**
15 * @var View $this 17 * @var View $this
16 * @var Label[] $labels 18 * @var Label[] $labels
  19 + * @var User[] $managers
17 * @var array $labelStatistics 20 * @var array $labelStatistics
18 * @var array $rejectionStatistics 21 * @var array $rejectionStatistics
19 * @var ActiveDataProvider $dataProvider 22 * @var ActiveDataProvider $dataProvider
20 - * @var array $labelChartData 23 + * @var array $labelChartData1
  24 + * @var array $labelChartData2
  25 + * @var array $labelChartData3
  26 + * @var array $rejectChartData1
  27 + * @var array $rejectChartData2
21 * @var string $dateValue 28 * @var string $dateValue
22 * @var int | boolean $dataLabel 29 * @var int | boolean $dataLabel
  30 + * @var int | boolean $dataManager
23 */ 31 */
  32 +
  33 + $js = <<< JS
  34 +$('[data-toggle="popover"]').popover();
  35 +JS;
  36 + $this->registerJs($js, View::POS_READY);
24 37
25 ?> 38 ?>
26 39
27 <div class="box box-default"> 40 <div class="box box-default">
28 <div class="box-header with-border"> 41 <div class="box-header with-border">
29 - <h3 class="box-title">Collapsable</h3> 42 + <h3 class="box-title">Поиск заказов</h3>
30 <div class="box-tools pull-right"> 43 <div class="box-tools pull-right">
31 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button> 44 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
32 </div><!-- /.box-tools --> 45 </div><!-- /.box-tools -->
@@ -37,7 +50,7 @@ @@ -37,7 +50,7 @@
37 'get' 50 'get'
38 ) ?> 51 ) ?>
39 <div class="row"> 52 <div class="row">
40 - <div class="col-md-4"> 53 + <div class="col-md-3">
41 <?= DateRangePicker::widget( 54 <?= DateRangePicker::widget(
42 [ 55 [
43 'name' => 'date_range', 56 'name' => 'date_range',
@@ -51,12 +64,12 @@ @@ -51,12 +64,12 @@
51 ] 64 ]
52 ) ?> 65 ) ?>
53 </div> 66 </div>
54 - <div class="col-md-6"> 67 + <div class="col-md-4">
55 <?= Select2::widget( 68 <?= Select2::widget(
56 [ 69 [
57 - 'name' => 'label',  
58 - 'value' => $dataLabel,  
59 - 'data' => ArrayHelper::map( 70 + 'name' => 'label',
  71 + 'value' => $dataLabel,
  72 + 'data' => ArrayHelper::map(
60 $labels, 73 $labels,
61 function($model) { 74 function($model) {
62 return $model->id; 75 return $model->id;
@@ -65,18 +78,41 @@ @@ -65,18 +78,41 @@
65 return $model->lang->title; 78 return $model->lang->title;
66 } 79 }
67 ), 80 ),
68 - 'options' => [  
69 - 'placeholder' => 'Все', 81 + 'options' => [
  82 + 'placeholder' => 'Все метки',
70 ], 83 ],
71 'pluginOptions' => [ 84 'pluginOptions' => [
72 - 'allowClear' => true, 85 + 'allowClear' => true,
  86 + ],
  87 + ]
  88 + ) ?>
  89 + </div>
  90 + <div class="col-md-3">
  91 + <?= Select2::widget(
  92 + [
  93 + 'name' => 'manager',
  94 + 'value' => $dataManager,
  95 + 'data' => ArrayHelper::map(
  96 + $managers,
  97 + function(User $model) {
  98 + return $model->id;
  99 + },
  100 + function(User $model) {
  101 + return $model->username;
  102 + }
  103 + ),
  104 + 'options' => [
  105 + 'placeholder' => 'Все менеджеры',
  106 + ],
  107 + 'pluginOptions' => [
  108 + 'allowClear' => true,
73 ], 109 ],
74 ] 110 ]
75 ) ?> 111 ) ?>
76 </div> 112 </div>
77 <div class="col-md-2"> 113 <div class="col-md-2">
78 <?= Html::submitButton( 114 <?= Html::submitButton(
79 - 'Go', 115 + 'Поиск',
80 [ 116 [
81 'class' => 'btn btn-success', 117 'class' => 'btn btn-success',
82 ] 118 ]
@@ -89,7 +125,7 @@ @@ -89,7 +125,7 @@
89 125
90 <div class="box box-default"> 126 <div class="box box-default">
91 <div class="box-header with-border"> 127 <div class="box-header with-border">
92 - <h3 class="box-title">Метки, статистика за </h3> 128 + <h3 class="box-title">Метки, статистика за <?= empty($dateValue) ? 'всё время' : $dateValue ?></h3>
93 <div class="box-tools pull-right"> 129 <div class="box-tools pull-right">
94 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button> 130 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
95 </div><!-- /.box-tools --> 131 </div><!-- /.box-tools -->
@@ -104,7 +140,15 @@ @@ -104,7 +140,15 @@
104 <td><b>Уникальных товаров, шт.</b></td> 140 <td><b>Уникальных товаров, шт.</b></td>
105 </tr> 141 </tr>
106 <?php 142 <?php
  143 + $total_count = 0;
  144 + $total_sum = 0;
  145 + $total_products = 0;
  146 + $total_unique = 0;
107 foreach ($labelStatistics as $name => $statistic) { 147 foreach ($labelStatistics as $name => $statistic) {
  148 + $total_count += $statistic[ 'count' ];
  149 + $total_sum += $statistic[ 'sum' ];
  150 + $total_products += $statistic[ 'products' ];
  151 + $total_unique += $statistic[ 'unique' ];
108 echo Html::tag( 152 echo Html::tag(
109 'tr', 153 'tr',
110 Html::tag('td', $name) . Html::tag('td', $statistic[ 'count' ]) . Html::tag( 154 Html::tag('td', $name) . Html::tag('td', $statistic[ 'count' ]) . Html::tag(
@@ -112,39 +156,116 @@ @@ -112,39 +156,116 @@
112 $statistic[ 'sum' ] 156 $statistic[ 'sum' ]
113 ) . Html::tag('td', $statistic[ 'products' ]) . Html::tag('td', $statistic[ 'unique' ]) 157 ) . Html::tag('td', $statistic[ 'products' ]) . Html::tag('td', $statistic[ 'unique' ])
114 ); 158 );
115 - } ?> 159 + }
  160 + ?>
  161 + <tr>
  162 + <td><b>Всего</b></td>
  163 + <td><b><?=$total_count?></b></td>
  164 + <td><b><?=$total_sum?></b></td>
  165 + <td><b><?=$total_products?></b></td>
  166 + <td><b><?=$total_unique?></b></td>
  167 + </tr>
116 </table> 168 </table>
117 -  
118 - <?= ChartJs::widget(  
119 - [  
120 - 'type' => 'bar',  
121 - 'options' => [  
122 - 'height' => 200,  
123 - 'width' => 600,  
124 - ],  
125 - 'data' => $labelChartData,  
126 - 'clientOptions' => [  
127 - 'title' => [  
128 - 'display' => true,  
129 - 'text' => 'Custom Chart Title',  
130 - ],  
131 - 'scales' => [  
132 - 'xAxes' => [  
133 - [  
134 - 'display' => false,  
135 - ],  
136 - ],  
137 - ],  
138 - ],  
139 - ]  
140 - ); ?>  
141 -  
142 </div><!-- /.box-body --> 169 </div><!-- /.box-body -->
  170 +
  171 + <div class="box-footer">
  172 + <div class="nav-tabs-custom">
  173 +
  174 + <!-- Nav tabs -->
  175 + <ul class="nav nav-tabs" role="tablist">
  176 + <li role="presentation" class="active">
  177 + <a href="#home" aria-controls="home" role="tab" data-toggle="tab">Заказы</a></li>
  178 + <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">Сумма</a></li>
  179 + <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">Товары</a>
  180 + </li>
  181 + </ul>
  182 +
  183 + <!-- Tab panes -->
  184 + <div class="tab-content">
  185 + <div role="tabpanel" class="tab-pane active" id="home">
  186 + <?= ChartJs::widget(
  187 + [
  188 + 'type' => 'bar',
  189 + 'options' => [
  190 + 'height' => 200,
  191 + 'width' => 600,
  192 + ],
  193 + 'data' => $labelChartData1,
  194 + 'clientOptions' => [
  195 + 'title' => [
  196 + 'display' => true,
  197 + 'text' => 'Статистика меток',
  198 + ],
  199 + 'scales' => [
  200 + 'xAxes' => [
  201 + [
  202 + 'display' => false,
  203 + ],
  204 + ],
  205 + ],
  206 + ],
  207 + ]
  208 + ); ?>
  209 + </div>
  210 + <div role="tabpanel" class="tab-pane" id="profile">
  211 + <?= ChartJs::widget(
  212 + [
  213 + 'type' => 'bar',
  214 + 'options' => [
  215 + 'height' => 200,
  216 + 'width' => 600,
  217 + ],
  218 + 'data' => $labelChartData2,
  219 + 'clientOptions' => [
  220 + 'title' => [
  221 + 'display' => true,
  222 + 'text' => 'Статистика меток',
  223 + ],
  224 + 'scales' => [
  225 + 'xAxes' => [
  226 + [
  227 + 'display' => false,
  228 + ],
  229 + ],
  230 + ],
  231 + ],
  232 + ]
  233 + ); ?>
  234 + </div>
  235 + <div role="tabpanel" class="tab-pane" id="messages">
  236 + <?= ChartJs::widget(
  237 + [
  238 + 'type' => 'bar',
  239 + 'options' => [
  240 + 'height' => 200,
  241 + 'width' => 600,
  242 + ],
  243 + 'data' => $labelChartData3,
  244 + 'clientOptions' => [
  245 + 'title' => [
  246 + 'display' => true,
  247 + 'text' => 'Статистика меток',
  248 + ],
  249 + 'scales' => [
  250 + 'xAxes' => [
  251 + [
  252 + 'display' => false,
  253 + ],
  254 + ],
  255 + ],
  256 + ],
  257 + ]
  258 + ); ?>
  259 + </div>
  260 + </div>
  261 +
  262 + </div>
  263 + </div>
143 </div><!-- /.box --> 264 </div><!-- /.box -->
144 265
145 <div class="box box-default"> 266 <div class="box box-default">
146 <div class="box-header with-border"> 267 <div class="box-header with-border">
147 - <h3 class="box-title">Метки, статистика за </h3> 268 + <h3 class="box-title">Причины отказа, статистика за <?= empty($dateValue) ? 'всё время' : $dateValue ?></h3>
148 <div class="box-tools pull-right"> 269 <div class="box-tools pull-right">
149 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button> 270 <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
150 </div><!-- /.box-tools --> 271 </div><!-- /.box-tools -->
@@ -169,77 +290,205 @@ @@ -169,77 +290,205 @@
169 ?> 290 ?>
170 </table> 291 </table>
171 </div><!-- /.box-body --> 292 </div><!-- /.box-body -->
172 -</div><!-- /.box -->  
173 293
174 -<?= GridView::widget(  
175 - [  
176 - 'dataProvider' => $dataProvider,  
177 - 'columns' => [  
178 - 'id',  
179 - 'created_at:datetime',  
180 - 'name',  
181 - 'city',  
182 - [  
183 - 'attribute' => 'orderLabel.label',  
184 - 'label' => 'Метка',  
185 - ],  
186 - 'total',  
187 - [  
188 - 'attribute' => 'reason',  
189 - 'content' => function($model) {  
190 - /**  
191 - * @var Order $model  
192 - */  
193 - if (empty($model->reason)) {  
194 - return '';  
195 - } else {  
196 - return Order::REASONS[ $model->reason ];  
197 - }  
198 - },  
199 - ],  
200 - [  
201 - 'attribute' => 'manager.username',  
202 - 'label' => 'Менеджер',  
203 - ],  
204 - [  
205 - 'attribute' => 'body',  
206 - 'content' => function($model) {  
207 - /**  
208 - * @var Order $model  
209 - */  
210 - if (empty($model->body)) {  
211 - return '';  
212 - } else {  
213 - return Html::a(  
214 - StringHelper::truncate($model->body, 10, '...'),  
215 - '#',  
216 - [  
217 - 'data-toggle' => 'tooltip',  
218 - 'title' => $model->body,  
219 - 'onclick' => 'event.preventDefault();',  
220 - ]  
221 - );  
222 - }  
223 - },  
224 - ],  
225 - [  
226 - 'content' => function($model) {  
227 - /**  
228 - * @var Order $model  
229 - */  
230 - return Html::a(  
231 - Html::tag('i', '', [ 'class' => 'glyphicon glyphicon-eye-open' ]),  
232 - [  
233 - '/ecommerce/order/view',  
234 - 'id' => $model->id, 294 + <div class="box-footer">
  295 + <div class="nav-tabs-custom">
  296 +
  297 + <!-- Nav tabs -->
  298 + <ul class="nav nav-tabs" role="tablist">
  299 + <li role="presentation" class="active">
  300 + <a href="#count" aria-controls="count" role="tab" data-toggle="tab">Заказы</a></li>
  301 + <li role="presentation"><a href="#sum" aria-controls="sum" role="tab" data-toggle="tab">Сумма</a></li>
  302 + </ul>
  303 +
  304 + <!-- Tab panes -->
  305 + <div class="tab-content">
  306 + <div role="tabpanel" class="tab-pane active" id="count">
  307 + <?= ChartJs::widget(
  308 + [
  309 + 'type' => 'bar',
  310 + 'options' => [
  311 + 'height' => 200,
  312 + 'width' => 600,
  313 + ],
  314 + 'data' => $rejectChartData1,
  315 + 'clientOptions' => [
  316 + 'title' => [
  317 + 'display' => true,
  318 + 'text' => 'Статистика отказов',
  319 + ],
  320 + 'scales' => [
  321 + 'xAxes' => [
  322 + [
  323 + 'display' => false,
  324 + ],
  325 + ],
  326 + ],
  327 + ],
  328 + ]
  329 + ); ?>
  330 + </div>
  331 + <div role="tabpanel" class="tab-pane" id="sum">
  332 + <?= ChartJs::widget(
  333 + [
  334 + 'type' => 'bar',
  335 + 'options' => [
  336 + 'height' => 200,
  337 + 'width' => 600,
  338 + ],
  339 + 'data' => $rejectChartData2,
  340 + 'clientOptions' => [
  341 + 'title' => [
  342 + 'display' => true,
  343 + 'text' => 'Статистика отказов',
235 ], 344 ],
236 - [  
237 - 'target' => '_blank',  
238 - 'data-pjax' => '0',  
239 - ]  
240 - );  
241 - },  
242 - ],  
243 - ],  
244 - ]  
245 -) ?> 345 + 'scales' => [
  346 + 'xAxes' => [
  347 + [
  348 + 'display' => false,
  349 + ],
  350 + ],
  351 + ],
  352 + ],
  353 + ]
  354 + ); ?>
  355 + </div>
  356 + </div>
  357 +
  358 + </div>
  359 + </div>
  360 +
  361 +</div><!-- /.box -->
  362 +
  363 +
  364 +<div class="box box-default">
  365 + <div class="box-header with-border">
  366 + <h3 class="box-title">Заказы</h3>
  367 + <div class="box-tools pull-right">
  368 + <button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
  369 + </div><!-- /.box-tools -->
  370 + </div><!-- /.box-header -->
  371 + <div class="box-body table-responsive">
  372 + <?= GridView::widget(
  373 + [
  374 + 'dataProvider' => $dataProvider,
  375 + 'columns' => [
  376 + 'id',
  377 + [
  378 + 'label' => 'Дата добавления',
  379 + 'content' => function(Order $model) {
  380 + return \Yii::$app->formatter->asDate($model->created_at) .
  381 + '<br>' . \Yii::$app->formatter->asTime($model->created_at);
  382 + },
  383 + ],
  384 + 'name',
  385 + [
  386 + 'label' => 'Товары',
  387 + 'content' => function(Order $model) {
  388 + if (empty($model->products)) {
  389 + return '';
  390 + } else {
  391 + $content = '';
  392 + $i = 0;
  393 + foreach ($model->products as $product) {
  394 + if(empty($product->productVariant)){
  395 + $image = '';
  396 + } else {
  397 + $image = $product->productVariant->imageUrl;
  398 + }
  399 + $i++;
  400 + $content .= Html::a(
  401 + $product->sku,
  402 + '#',
  403 + [
  404 + 'onclick' => 'event.preventDefault();',
  405 + 'data-toggle' => 'popover',
  406 + 'data-placement' => 'right',
  407 + 'data-html' => 'true',
  408 + 'data-content' => Html::img(
  409 + $image,
  410 + [
  411 + 'class' => 'img-rounded',
  412 + ]
  413 + ) . Html::tag('p', $product->product_name),
  414 + ]
  415 + );
  416 + if ($i != count($model->products)) {
  417 + $content .= ', ';
  418 + }
  419 + if ($i % 2 == 0) {
  420 + $content .= '<br>';
  421 + }
  422 + }
  423 + return $content;
  424 + }
  425 + },
  426 + ],
  427 + 'city',
  428 + [
  429 + 'attribute' => 'orderLabel.label',
  430 + 'label' => 'Метка',
  431 + ],
  432 + 'total',
  433 + [
  434 + 'attribute' => 'reason',
  435 + 'content' => function($model) {
  436 + /**
  437 + * @var Order $model
  438 + */
  439 + if (empty($model->reason)) {
  440 + return '';
  441 + } else {
  442 + return Order::REASONS[ $model->reason ];
  443 + }
  444 + },
  445 + ],
  446 + [
  447 + 'attribute' => 'manager.username',
  448 + 'label' => 'Менеджер',
  449 + ],
  450 + [
  451 + 'attribute' => 'body',
  452 + 'content' => function($model) {
  453 + /**
  454 + * @var Order $model
  455 + */
  456 + if (empty($model->body)) {
  457 + return '';
  458 + } else {
  459 + return Html::a(
  460 + StringHelper::truncate($model->body, 10, '...'),
  461 + '#',
  462 + [
  463 + 'data-toggle' => 'tooltip',
  464 + 'title' => $model->body,
  465 + 'onclick' => 'event.preventDefault();',
  466 + ]
  467 + );
  468 + }
  469 + },
  470 + ],
  471 + [
  472 + 'content' => function($model) {
  473 + /**
  474 + * @var Order $model
  475 + */
  476 + return Html::a(
  477 + Html::tag('i', '', [ 'class' => 'glyphicon glyphicon-eye-open' ]),
  478 + [
  479 + '/ecommerce/order/view',
  480 + 'id' => $model->id,
  481 + ],
  482 + [
  483 + 'target' => '_blank',
  484 + 'data-pjax' => '0',
  485 + ]
  486 + );
  487 + },
  488 + ],
  489 + ],
  490 + ]
  491 + ) ?>
  492 +
  493 + </div><!-- /.box-body -->
  494 +</div><!-- /.box -->