### Первоначальный запуск
```shell
docker compose up -d
-docker compose exec php composer install
-docker compose exec php composer -o dump-autoload
-docker compose exec php mkdir /www/web/uploads
-docker compose exec php chmod -R 777 /www/web/uploads
+docker compose exec php-yii_erp24 composer install
+docker compose exec php-yii_erp24 composer -o dump-autoload
+docker compose exec php-yii_erp24 mkdir /www/web/uploads
+docker compose exec php-yii_erp24 chmod -R 777 /www/web/uploads
docker compose run --no-deps --rm node-yii_erp24 npm install
docker compose up -d node-yii_erp24
-gzip -d -c erp24.sql.gz | docker compose exec -T db mysql -proot_password erp24
+gzip -d -c erp24.sql.gz | docker compose exec -T db-yii_erp24 mysql -proot_password erp24
```
### Выкладка
Перед выкладкой выполнить
```shell
-docker compose run --rm node sh -c "npm install && npm run prod && cp -r /www/dist-prod/* /www/dist"
+docker compose run --rm node-yii_erp24 sh -c "npm install && npm run prod && cp -r /www/dist-prod/* /www/dist"
```
Скопировать dist и нужные папки в продакшн
### Выгрузка базы в сжатый sql
```shell
-docker compose exec db mysqldump -proot_password erp24 > erp24.sql && gzip erp24.sql
+docker compose exec db-yii_erp24 mysql mysqldump -proot_password erp24 > erp24.sql && gzip erp24.sql
```
### Разработка
-* [Работа с gii](doc/gii.md)
\ No newline at end of file
+* [Работа с gii](doc/gii.md)
+
+### Перенести данные в Pgsql
+* Нужно раскомментировать в docker-compose.yml "pgloader-mysql-yii_erp24 ...."
+* И поднять этот контейнер
\ No newline at end of file
+++ /dev/null
-<?php
-
-namespace app\controllers;
-
-use Yii;
-use yii\data\ArrayDataProvider;
-use yii\db\Exception;
-use yii\db\Expression;
-use yii\helpers\ArrayHelper;
-use yii\helpers\Json;
-use yii\web\Controller;
-use yii_app\records\Admin;
-use yii_app\records\ChartDataSearch;
-use yii_app\records\WriteOffs;
-
-class ChartForManagementController extends Controller
-{
- public function actionIndex()
- {
- $admin = Admin::findOne(['id' => Yii::$app->user->id]);
-
- $access_chart = [
- 'mode_level' => [],
- 'mode_shift' => [],
- 'visible' => false,
- ];
-
- $access = [
- 'main' => $access_chart,
- 'plan_completed_this_day' => $access_chart,
- 'plan_completed_this_month' => $access_chart,
- 'sales' => $access_chart,
- 'matrix_sales_sum' => $access_chart,
- 'avg_sales_value' => $access_chart,
- 'fot' => $access_chart,
- 'sales_sum_on_admin' => $access_chart,
- 'user_bonus' => $access_chart,
- 'count_sales_in_hour' => $access_chart,
- 'write_offs' => $access_chart,
- ];
-
- if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
- foreach ($access as $key => &$item) {
- if ($key === 'sales' || $key === 'avg_sales_value') {
- $item['mode_level'] = [
- //0 => 'Доставка',
- 1 => 'Розница',
- 2 => 'Куст',
- 3 => 'Магазин'
- ];
- } else {
- $item['mode_level'] = [
- 1 => 'Розница',
- 2 => 'Куст',
- 3 => 'Магазин'
- ];
- }
-
-
- $item['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
- //4 => 'Сутки'
- ];
-
- $item['visible'] = true;
- }
-
- } else if (in_array($admin->group_id, [Admin::CLUSTER_MANAGER_GROUP_ID])) {
- foreach ($access as &$item) {
- $item['mode_level'] = [
- 2 => 'Куст',
- 3 => 'Магазин',
- ];
-
- $item['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
-
- ];
-
- $item['visible'] = true;
- }
-
- } else if (in_array($admin->group_id, [30, 40])) {
- foreach ($access as $key => &$item) {
- $item['mode_level'] = [
- 3 => 'Магазин',
- ];
-
- $item['mode_shift'] = [
- 1 => 'День',
- ];
-
- if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
- $item['visible'] = true;
- }
-
- }
-
- } else if (in_array($admin->group_id, [35, 72])) {
- foreach ($access as $key => &$item) {
- $item['mode_level'] = [
- 3 => 'Магазин',
- ];
-
- $item['mode_shift'] = [
- 2 => 'Ночь',
- ];
-
- if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
- $item['visible'] = true;
- }
-
- }
-
- } else if (in_array($admin->group_id, [Admin::ADMINISTRATOR_GROUP_ID])) {
- foreach ($access as &$item) {
- $item['mode_level'] = [
- 3 => 'Магазин'
- ];
-
- $item['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
-
- ];
-
- $item['visible'] = true;
- }
-
- } else {
- throw new Exception('Нет доступа');
- }
-
- return $this->render('index', [
- 'access' => $access
- ]);
- }
-
- public function actionWriteOffPosition()
- {
- $admin = Admin::findOne(['id' => Yii::$app->user->id]);
-
- $access = [
- 'mode_level' => [],
- 'mode_shift' => [],
- 'access_plan' => false,
- ];
-
- if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
-
- $access['mode_level'] = [
- 1 => 'Розница',
- 2 => 'Куст',
- 3 => 'Магазин'
- ];
-
- $access['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
-
- ];
-
- $access['access_plan'] = true;
-
- } else if (in_array($admin->group_id, [7])) {
-
- $access['mode_level'] = [
- 2 => 'Куст',
- 3 => 'Магазин',
- ];
-
- $access['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
- ];
-
- $access['access_plan'] = true;
-
- } else if (in_array($admin->group_id, [30, 40])) {
-
- $access['mode_level'] = [
- 3 => 'Магазин',
- ];
-
- $access['mode_shift'] = [
- 1 => 'День',
- ];
-
- } else if (in_array($admin->group_id, [35, 72])) {
-
- $access['mode_level'] = [
- 3 => 'Магазин',
- ];
-
- $access['mode_shift'] = [
- 2 => 'Ночь',
- ];
-
- } else if (in_array($admin->group_id, [50])) {
- $access['mode_level'] = [
- 3 => 'Магазин'
- ];
-
- $access['mode_shift'] = [
- 3 => 'День+Ночь',
- 1 => 'День',
- 2 => 'Ночь',
- ];
-
- $access['access_plan'] = true;
- } else {
- throw new Exception('Нет доступа');
- }
-
- return $this->render('write-offs-position-chart', [
- 'access' => $access
- ]);
- }
-
- public function actionGetControlDataAjax()
- {
- $post_data = Yii::$app->request->post();
-
- $date_start = date('Y-m-d H:i:s', strtotime($post_data['date_start']));
- $date_end = date('Y-m-d H:i:s', strtotime($post_data['date_end']));
-
- $stores = Admin::find()->where(['admin.id' => Yii::$app->user->id])->leftJoin(
- 'store_dynamic',
- [
- 'OR',
- ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, ",%")')],
- ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, ",%")')],
- ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, "")')],
- ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, "")')],
- ]
-
- )
- ->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1')
- ->select(
- [
- 'cluster_name' => 'CONCAT_WS(\' \', \'Куст\', store_dynamic.value_int)',
- 'cluster_id' => 'store_dynamic.value_int',
- 'store_id' => 'store_dynamic.store_id',
- 'store_name' => 'city_store.name',
- 'date_from' => 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')',
- ]
- )
- ->andWhere(
- [
- 'OR',
- [
- 'AND',
- ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
- ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
- ],
- [
- 'AND',
- ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
- ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_end],
- ],
- [
- 'AND',
- ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
- ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
- ],
- [
- 'AND',
- ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
- ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start],
- ],
- ]
- )
- ->orderBy(['store_dynamic.value_int' => SORT_ASC, 'city_store.id' => SORT_ASC])
- ->asArray()
- ->all();
-
- $steps_stores = ArrayHelper::map($stores, 'date_from', 'cluster_name', 'store_name');
-
- foreach ($steps_stores as $store_name => $step_store) {
- if (count($step_store) === 1) {
- unset($steps_stores[$store_name]);
- }
- }
-
- $clusters_unic = [];
- foreach ($stores as $store) {
- if (!in_array(['id' => $store['cluster_id'], 'text' => $store['cluster_name']], $clusters_unic)) {
- $clusters_unic[] = ['id' => $store['cluster_id'], 'text' => $store['cluster_name']];
- }
- }
-
- $store_in_cluster = [];
- foreach ($stores as $store) {
- if (!isset($store_in_cluster[$store['cluster_id']])) {
- $store_in_cluster[$store['cluster_id']]['text'] = $store['cluster_name'];
- }
- $store_in_cluster[$store['cluster_id']]['children'][] = ['id' => $store['store_id'], 'text' => $store['store_name']];
- }
-
- return Json::encode(['stores_step' => $steps_stores, 'clusters' => $clusters_unic, 'stores_in_cluster' => $store_in_cluster]);
- }
-
- public function actionGetDataAjax()
- {
- $post_data = Yii::$app->request->post();
- $chart_data_search = new ChartDataSearch();
-
- $chart_data_search->mode_level = intval($post_data['mode']);
- $chart_data_search->attribute_name = $post_data['attribute'];
- $chart_data_search->date_start = $post_data['date_start'] ?? date('Y-m-d', strtotime('-13 day'));
- $chart_data_search->date_end = $post_data['date_end'] ?? date('Y-m-d', time());
- $chart_data_search->cluster_id = $post_data['cluster'];
- $chart_data_search->store_id = $post_data['store'];
- $chart_data_search->mode_shift = $post_data['shift'] ?? 3;
- $chart_data_search->select_cluster = true;
-
- if ($post_data['attribute'] === 'plan_completed_this_day') {
- $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
- $chart_data_search->date_end = date('Y-m-d', time());
-
- }
-
- if ($post_data['attribute'] === 'plan_completed_this_month') {
- $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
- $chart_data_search->date_end = date('Y-m-d', strtotime('last day of this month'));
-
- }
-
- if ($post_data['attribute'] === 'write_offs') {
- $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month', strtotime($chart_data_search->date_start)));
- }
-
- $dates = [];
- $chart_opts = null;
- $temp_row = ['sales_sum' => 0, 'sum' => 0, 'plan' => 0];
- $interval_days = (strtotime($chart_data_search->date_end) - strtotime($chart_data_search->date_start)) / (60 * 60 * 24);
-
- $data_answer = $chart_data_search->attributes_config[$post_data['attribute']];
-
- if ($post_data['attribute'] === 'write_offs_position') {
- $answer_query = $chart_data_search->searchWriteOffsItems();
- }
-
- if ($post_data['attribute'] === 'write_offs_position') {
- if (!isset($answer_query[1])) {
- return -1;
- }
-
- $data = $answer_query[1];
-
- } else {
- $data = $chart_data_search->search();
-
- }
-
- $keys = array_keys($data_answer['attribute']);
- $step = 0;
-
- foreach ($data as $index => $datum) {
- if ($post_data['attribute'] === 'plan_completed_this_day') {
- $temp_row['sales_sum'] += $datum['value'];
- $temp_row['plan'] += $datum['plan'];
-
- } else if ($post_data['attribute'] === 'plan_completed_this_month') {
- $temp_row['sales_sum'] += $datum['value'];
- $temp_row['plan'] += $datum['plan'];
-
- } else if ($post_data['attribute'] === 'sales') {
- $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
-
- } else if ($post_data['attribute'] === 'count_sales_in_hour') {
- $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
- $data_answer['attribute'][$keys[1]]['data'][] = $datum['value'] / $interval_days;
-
- } else if ($post_data['attribute'] === 'avg_sales_value') {
- if ($step % 2 != 0) {
- $step++;
- continue;
- }
-
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
- $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
- $step++;
-
- } else if ($post_data['attribute'] === 'fot') {
- if ($step % 2 != 0) {
- $step ++;
- continue;
-
- }
-
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / (($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1) / 100);
- $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
- $step++;
-
- } else if ($post_data['attribute'] === 'sales_sum_on_admin') {
- if ($step % 2 != 0) {
- $step ++;
- continue;
-
- }
-
- $step++;
-
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
-
- } else if ($post_data['attribute'] === 'write_offs') {
- if ($step % 2 != 0) {
- $step++;
- continue;
-
- }
-
- $step++;
-
- if (date('d', strtotime($datum['date'])) == 1) {
- $temp_row['sales_sum'] = 0;
- $temp_row['sum'] = 0;
- }
- $temp_row['sales_sum'] += $datum['value'] ?? 0;
- $temp_row['sum'] += $data[$index + 1]['value'] ?? 0;
-
- if (strtotime($datum['date']) >= (($post_data['date_start']) ? strtotime($post_data['date_start']) : date('Y-m-d', strtotime('-13 day')))) {
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $data[$index + 1]['value'] ?? 0;
- $data_answer['attribute'][$keys[1]]['data'][] = ($data[$index + 1]['value'] ?? 0) / (($datum['value'] != 0 ? $datum['value'] : 1) / 100);
- $data_answer['attribute'][$keys[2]]['data'][] = $temp_row['sum'] / ((($temp_row['sales_sum'] != 0) ? $temp_row['sales_sum'] : 1) / 100);
- }
- } else if ($post_data['attribute'] === 'user_bonus') {
- if ($step % 4 == 0) {
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
- $data_answer['attribute'][$keys[1]]['data'][] = 0;
- $data_answer['attribute'][$keys[2]]['data'][] = 0;
- $data_answer['attribute'][$keys[3]]['data'][] = 0;
-
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = 0;
- $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
- $data_answer['attribute'][$keys[2]]['data'][] = 0;
- $data_answer['attribute'][$keys[3]]['data'][] = 0;
-
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = 0;
- $data_answer['attribute'][$keys[1]]['data'][] = 0;
- $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
- $data_answer['attribute'][$keys[3]]['data'][] = $data[$index + 3]['value'] ?? 0;
-
- }
-
- $step++;
-
- } else if ($post_data['attribute'] === 'matrix_sales_sum') {
- if ($step % 3 == 0) {
- $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
- $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
- $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
- $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
-
- }
-
- $step++;
- }
- }
-
- if ($post_data['attribute'] !== 'count_sales_in_hour') {
- $chart_opts = [
- 'xaxis' => [
- 'type' => 'text',
- 'categories' => $dates,
- ]
- ];
- } else {
- if ($chart_data_search->mode_shift === 3) {
- $chart_opts = [
- 'xaxis' => [
- 'type' => 'text',
- 'categories' => array_merge(range(8, 23), range(0, 7))
- ]
- ];
- } else if ($chart_data_search->mode_shift === 1) {
- $chart_opts = [
- 'xaxis' => [
- 'type' => 'text',
- 'categories' => range(8, 19)
- ]
- ];
- } else if ($chart_data_search->mode_shift === 2) {
- $chart_opts = [
- 'xaxis' => [
- 'type' => 'text',
- 'categories' => array_merge(range(20, 23), range(0, 7))
- ]
- ];
- }
-
- $chart_data_search::sortCountSalesInHour($data_answer, $chart_data_search->mode_shift);
- }
-
- if ($chart_data_search->mode_level === 2) {
- $chart_opts['title'] = ['text' => 'Куст ' . $chart_data_search->cluster_id];
- } else if ($chart_data_search->mode_level === 3) {
- if ($chart_data_search->attribute_name === 'write_offs_position') {
- $chart_opts['title'] = ['text' => 'Магазин: ' . $answer_query[0][0]['store_name']];
- } else {
- $chart_opts['title'] = ['text' => 'Магазин: ' . $data[0]['store_name']];
- }
-
- } else {
- $chart_opts['title'] = ['text' => 'Розница'];
- }
-
- if ($post_data['attribute'] === 'plan_completed_this_day') {
- $data_answer = [];
- $data_answer['attribute']['plan_complete_on_this_day'] = round(
- $temp_row['sales_sum'] /
- ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
- 100,
- 2);
-
- }
-
- if ($post_data['attribute'] === 'plan_completed_this_month') {
- $data_answer = [];
- $data_answer['attribute']['plan_hypothesis_complete_on_this_month'] = round(
- $temp_row['sales_sum'] /
- date('d', time()) *
- date('d', strtotime('last day of this month')) /
- ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
- 100,
- 2);
-
- }
-
- $answer = ['chart_opts' => $chart_opts, 'data_answer' => $data_answer];
- return Json::encode($answer);
- }
-
- public function actionWriteOffsIndex($date, $cluster_id = null, $store_id = null)
- {
- $query_write_offs = WriteOffs::find()
- ->select([
- 'store_name' => 'city_store.name',
- 'sum' => 'write_offs.summ',
- 'date' => 'write_offs.date',
- 'number' => 'write_offs.number',
- 'comment' => 'write_offs.comment'
- ])
- ->innerJoin('export_import_table', 'export_import_table.export_val = write_offs.store_id')
- ->innerJoin('city_store', 'city_store.id = export_import_table.entity_id')
- ->innerJoin(
- 'store_dynamic',
- [
- 'AND',
- 'store_dynamic.store_id = city_store.id',
- [
- '>=',
- new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
- new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
- ],
- [
- '<',
- new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
- new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
- ]
- ]
- )
- ->andWhere([
- 'export_import_table.entity' => 'city_store'
- ])
- ->andFilterWhere([
- 'store_dynamic.value_int' => $cluster_id,
- 'city_store.id' => $store_id
- ])
- ->andWhere([
- 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')' => $date
- ])
- ->andWhere([
- 'write_offs.type' => 'Брак'
- ])
- ->orderBy([
- 'store_dynamic.value_int' => SORT_ASC,
- 'city_store.id' => SORT_ASC,
- 'write_offs.date' => SORT_ASC,
- ]);
-
- $dataProvider = new ArrayDataProvider([
- 'allModels' => $query_write_offs->asArray()->all()
- ]);
-
- return $this->render('write-offs', [
- 'dataProvider' => $dataProvider,
- 'date' => $date
- ]);
- }
-
-}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace app\controllers;
+
+use Yii;
+use yii\data\ArrayDataProvider;
+use yii\db\Exception;
+use yii\db\Expression;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Json;
+use yii\web\Controller;
+use yii_app\records\Admin;
+use yii_app\records\ChartDataSearch;
+use yii_app\records\WriteOffs;
+
+class ChartsForManagementController extends Controller
+{
+ public function actionIndex()
+ {
+ $admin = Admin::findOne(['id' => Yii::$app->user->id]);
+
+ $access_chart = [
+ 'mode_level' => [],
+ 'mode_shift' => [],
+ 'visible' => false,
+ ];
+
+ $access = [
+ 'main' => $access_chart,
+ 'plan_completed_this_day' => $access_chart,
+ 'plan_completed_this_month' => $access_chart,
+ 'sales' => $access_chart,
+ 'matrix_sales_sum' => $access_chart,
+ 'avg_sales_value' => $access_chart,
+ 'fot' => $access_chart,
+ 'sales_sum_on_admin' => $access_chart,
+ 'user_bonus' => $access_chart,
+ 'count_sales_in_hour' => $access_chart,
+ 'write_offs' => $access_chart,
+ ];
+
+ if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
+ foreach ($access as $key => &$item) {
+ if ($key === 'sales' || $key === 'avg_sales_value') {
+ $item['mode_level'] = [
+ //0 => 'Доставка',
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+ } else {
+ $item['mode_level'] = [
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+ }
+
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ //4 => 'Сутки'
+ ];
+
+ $item['visible'] = true;
+ }
+
+ } else if (in_array($admin->group_id, [Admin::CLUSTER_MANAGER_GROUP_ID])) {
+ foreach ($access as &$item) {
+ $item['mode_level'] = [
+ 2 => 'Куст',
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $item['visible'] = true;
+ }
+
+ } else if (in_array($admin->group_id, [30, 40])) {
+ foreach ($access as $key => &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 1 => 'День',
+ ];
+
+ if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
+ $item['visible'] = true;
+ }
+
+ }
+
+ } else if (in_array($admin->group_id, [35, 72])) {
+ foreach ($access as $key => &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $item['mode_shift'] = [
+ 2 => 'Ночь',
+ ];
+
+ if ($key != 'plan_completed_this_day' && $key != 'plan_completed_this_month') {
+ $item['visible'] = true;
+ }
+
+ }
+
+ } else if (in_array($admin->group_id, [Admin::ADMINISTRATOR_GROUP_ID])) {
+ foreach ($access as &$item) {
+ $item['mode_level'] = [
+ 3 => 'Магазин'
+ ];
+
+ $item['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $item['visible'] = true;
+ }
+
+ } else {
+ throw new Exception('Нет доступа');
+ }
+
+ return $this->render('index', [
+ 'access' => $access
+ ]);
+ }
+
+ public function actionWriteOffPosition()
+ {
+ $admin = Admin::findOne(['id' => Yii::$app->user->id]);
+
+ $access = [
+ 'mode_level' => [],
+ 'mode_shift' => [],
+ 'access_plan' => false,
+ ];
+
+ if (in_array($admin->group_id, [1, 81, 71, 51, 10, 9, 74, 14])) {
+
+ $access['mode_level'] = [
+ 1 => 'Розница',
+ 2 => 'Куст',
+ 3 => 'Магазин'
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+
+ ];
+
+ $access['access_plan'] = true;
+
+ } else if (in_array($admin->group_id, [7])) {
+
+ $access['mode_level'] = [
+ 2 => 'Куст',
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ ];
+
+ $access['access_plan'] = true;
+
+ } else if (in_array($admin->group_id, [30, 40])) {
+
+ $access['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 1 => 'День',
+ ];
+
+ } else if (in_array($admin->group_id, [35, 72])) {
+
+ $access['mode_level'] = [
+ 3 => 'Магазин',
+ ];
+
+ $access['mode_shift'] = [
+ 2 => 'Ночь',
+ ];
+
+ } else if (in_array($admin->group_id, [50])) {
+ $access['mode_level'] = [
+ 3 => 'Магазин'
+ ];
+
+ $access['mode_shift'] = [
+ 3 => 'День+Ночь',
+ 1 => 'День',
+ 2 => 'Ночь',
+ ];
+
+ $access['access_plan'] = true;
+ } else {
+ throw new Exception('Нет доступа');
+ }
+
+ return $this->render('write-offs-position-chart', [
+ 'access' => $access
+ ]);
+ }
+
+ public function actionGetControlDataAjax()
+ {
+ $post_data = Yii::$app->request->post();
+
+ $date_start = date('Y-m-d H:i:s', strtotime($post_data['date_start']));
+ $date_end = date('Y-m-d H:i:s', strtotime($post_data['date_end']));
+
+ $stores = Admin::find()->where(['admin.id' => Yii::$app->user->id])->leftJoin(
+ 'store_dynamic',
+ [
+ 'OR',
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, ",%")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, ",%")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("%," , store_dynamic.store_id, "")')],
+ ['LIKE', 'admin.store_arr', new Expression('CONCAT("" , store_dynamic.store_id, "")')],
+ ]
+
+ )
+ ->innerJoin('city_store', 'store_dynamic.store_id = city_store.id AND store_dynamic.category = 1')
+ ->select(
+ [
+ 'cluster_name' => 'CONCAT_WS(\' \', \'Куст\', store_dynamic.value_int)',
+ 'cluster_id' => 'store_dynamic.value_int',
+ 'store_id' => 'store_dynamic.store_id',
+ 'store_name' => 'city_store.name',
+ 'date_from' => 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')',
+ ]
+ )
+ ->andWhere(
+ [
+ 'OR',
+ [
+ 'AND',
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ],
+ [
+ 'AND',
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_end],
+ ],
+ [
+ 'AND',
+ ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ['BETWEEN', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start, $date_end],
+ ],
+ [
+ 'AND',
+ ['<=', 'DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ['>=', 'DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d %H:%i:%s\')', $date_start],
+ ],
+ ]
+ )
+ ->orderBy(['store_dynamic.value_int' => SORT_ASC, 'city_store.id' => SORT_ASC])
+ ->asArray()
+ ->all();
+
+ $steps_stores = ArrayHelper::map($stores, 'date_from', 'cluster_name', 'store_name');
+
+ foreach ($steps_stores as $store_name => $step_store) {
+ if (count($step_store) === 1) {
+ unset($steps_stores[$store_name]);
+ }
+ }
+
+ $clusters_unic = [];
+ foreach ($stores as $store) {
+ if (!in_array(['id' => $store['cluster_id'], 'text' => $store['cluster_name']], $clusters_unic)) {
+ $clusters_unic[] = ['id' => $store['cluster_id'], 'text' => $store['cluster_name']];
+ }
+ }
+
+ $store_in_cluster = [];
+ foreach ($stores as $store) {
+ if (!isset($store_in_cluster[$store['cluster_id']])) {
+ $store_in_cluster[$store['cluster_id']]['text'] = $store['cluster_name'];
+ }
+ $store_in_cluster[$store['cluster_id']]['children'][] = ['id' => $store['store_id'], 'text' => $store['store_name']];
+ }
+
+ return Json::encode(['stores_step' => $steps_stores, 'clusters' => $clusters_unic, 'stores_in_cluster' => $store_in_cluster]);
+ }
+
+ public function actionGetDataAjax()
+ {
+ $post_data = Yii::$app->request->post();
+ $chart_data_search = new ChartDataSearch();
+
+ $chart_data_search->mode_level = intval($post_data['mode']);
+ $chart_data_search->attribute_name = $post_data['attribute'];
+ $chart_data_search->date_start = $post_data['date_start'] ?? date('Y-m-d', strtotime('-13 day'));
+ $chart_data_search->date_end = $post_data['date_end'] ?? date('Y-m-d', time());
+ $chart_data_search->cluster_id = $post_data['cluster'];
+ $chart_data_search->store_id = $post_data['store'];
+ $chart_data_search->mode_shift = $post_data['shift'] ?? 3;
+ $chart_data_search->select_cluster = true;
+
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
+ $chart_data_search->date_end = date('Y-m-d', time());
+
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month'));
+ $chart_data_search->date_end = date('Y-m-d', strtotime('last day of this month'));
+
+ }
+
+ if ($post_data['attribute'] === 'write_offs') {
+ $chart_data_search->date_start = date('Y-m-d', strtotime('first day of this month', strtotime($chart_data_search->date_start)));
+ }
+
+ $dates = [];
+ $chart_opts = null;
+ $temp_row = ['sales_sum' => 0, 'sum' => 0, 'plan' => 0];
+ $interval_days = (strtotime($chart_data_search->date_end) - strtotime($chart_data_search->date_start)) / (60 * 60 * 24);
+
+ $data_answer = $chart_data_search->attributes_config[$post_data['attribute']];
+
+ if ($post_data['attribute'] === 'write_offs_position') {
+ $answer_query = $chart_data_search->searchWriteOffsItems();
+ }
+
+ if ($post_data['attribute'] === 'write_offs_position') {
+ if (!isset($answer_query[1])) {
+ return -1;
+ }
+
+ $data = $answer_query[1];
+
+ } else {
+ $data = $chart_data_search->search();
+
+ }
+
+ $keys = array_keys($data_answer['attribute']);
+ $step = 0;
+
+ foreach ($data as $index => $datum) {
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $temp_row['sales_sum'] += $datum['value'];
+ $temp_row['plan'] += $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $temp_row['sales_sum'] += $datum['value'];
+ $temp_row['plan'] += $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'sales') {
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+
+ } else if ($post_data['attribute'] === 'count_sales_in_hour') {
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'];
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['value'] / $interval_days;
+
+ } else if ($post_data['attribute'] === 'avg_sales_value') {
+ if ($step % 2 != 0) {
+ $step++;
+ continue;
+ }
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+ $step++;
+
+ } else if ($post_data['attribute'] === 'fot') {
+ if ($step % 2 != 0) {
+ $step ++;
+ continue;
+
+ }
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / (($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1) / 100);
+ $data_answer['attribute'][$keys[1]]['data'][] = $datum['plan'];
+ $step++;
+
+ } else if ($post_data['attribute'] === 'sales_sum_on_admin') {
+ if ($step % 2 != 0) {
+ $step ++;
+ continue;
+
+ }
+
+ $step++;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $datum['value'] / ($data[$index + 1]['value'] != 0 ? $data[$index + 1]['value'] : 1);
+
+ } else if ($post_data['attribute'] === 'write_offs') {
+ if ($step % 2 != 0) {
+ $step++;
+ continue;
+
+ }
+
+ $step++;
+
+ if (date('d', strtotime($datum['date'])) == 1) {
+ $temp_row['sales_sum'] = 0;
+ $temp_row['sum'] = 0;
+ }
+ $temp_row['sales_sum'] += $datum['value'] ?? 0;
+ $temp_row['sum'] += $data[$index + 1]['value'] ?? 0;
+
+ if (strtotime($datum['date']) >= (($post_data['date_start']) ? strtotime($post_data['date_start']) : date('Y-m-d', strtotime('-13 day')))) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = ($data[$index + 1]['value'] ?? 0) / (($datum['value'] != 0 ? $datum['value'] : 1) / 100);
+ $data_answer['attribute'][$keys[2]]['data'][] = $temp_row['sum'] / ((($temp_row['sales_sum'] != 0) ? $temp_row['sales_sum'] : 1) / 100);
+ }
+ } else if ($post_data['attribute'] === 'user_bonus') {
+ if ($step % 4 == 0) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = 0;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = 0;
+
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
+ $data_answer['attribute'][$keys[3]]['data'][] = $data[$index + 3]['value'] ?? 0;
+
+ }
+
+ $step++;
+
+ } else if ($post_data['attribute'] === 'matrix_sales_sum') {
+ if ($step % 3 == 0) {
+ $dates[] = $datum['date'] . ' ' . $chart_data_search->day_of_week[date('w', strtotime($datum['date']))];
+ $data_answer['attribute'][$keys[0]]['data'][] = $data[$index]['value'] ?? 0;
+ $data_answer['attribute'][$keys[1]]['data'][] = $data[$index + 1]['value'] ?? 0;
+ $data_answer['attribute'][$keys[2]]['data'][] = $data[$index + 2]['value'] ?? 0;
+
+ }
+
+ $step++;
+ }
+ }
+
+ if ($post_data['attribute'] !== 'count_sales_in_hour') {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => $dates,
+ ]
+ ];
+ } else {
+ if ($chart_data_search->mode_shift === 3) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => array_merge(range(8, 23), range(0, 7))
+ ]
+ ];
+ } else if ($chart_data_search->mode_shift === 1) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => range(8, 19)
+ ]
+ ];
+ } else if ($chart_data_search->mode_shift === 2) {
+ $chart_opts = [
+ 'xaxis' => [
+ 'type' => 'text',
+ 'categories' => array_merge(range(20, 23), range(0, 7))
+ ]
+ ];
+ }
+
+ $chart_data_search::sortCountSalesInHour($data_answer, $chart_data_search->mode_shift);
+ }
+
+ if ($chart_data_search->mode_level === 2) {
+ $chart_opts['title'] = ['text' => 'Куст ' . $chart_data_search->cluster_id];
+ } else if ($chart_data_search->mode_level === 3) {
+ if ($chart_data_search->attribute_name === 'write_offs_position') {
+ $chart_opts['title'] = ['text' => 'Магазин: ' . $answer_query[0][0]['store_name']];
+ } else {
+ $chart_opts['title'] = ['text' => 'Магазин: ' . $data[0]['store_name']];
+ }
+
+ } else {
+ $chart_opts['title'] = ['text' => 'Розница'];
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_day') {
+ $data_answer = [];
+ $data_answer['attribute']['plan_complete_on_this_day'] = round(
+ $temp_row['sales_sum'] /
+ ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
+ 100,
+ 2);
+
+ }
+
+ if ($post_data['attribute'] === 'plan_completed_this_month') {
+ $data_answer = [];
+ $data_answer['attribute']['plan_hypothesis_complete_on_this_month'] = round(
+ $temp_row['sales_sum'] /
+ date('d', time()) *
+ date('d', strtotime('last day of this month')) /
+ ($temp_row['plan'] !== 0 ? $temp_row['plan'] : 1) *
+ 100,
+ 2);
+
+ }
+
+ $answer = ['chart_opts' => $chart_opts, 'data_answer' => $data_answer];
+ return Json::encode($answer);
+ }
+
+ public function actionWriteOffsIndex($date, $cluster_id = null, $store_id = null)
+ {
+ $query_write_offs = WriteOffs::find()
+ ->select([
+ 'store_name' => 'city_store.name',
+ 'sum' => 'write_offs.summ',
+ 'date' => 'write_offs.date',
+ 'number' => 'write_offs.number',
+ 'comment' => 'write_offs.comment'
+ ])
+ ->innerJoin('export_import_table', 'export_import_table.export_val = write_offs.store_id')
+ ->innerJoin('city_store', 'city_store.id = export_import_table.entity_id')
+ ->innerJoin(
+ 'store_dynamic',
+ [
+ 'AND',
+ 'store_dynamic.store_id = city_store.id',
+ [
+ '>=',
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_from, \'%Y-%m-%d\')'),
+ ],
+ [
+ '<',
+ new Expression('DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')'),
+ new Expression('DATE_FORMAT(store_dynamic.date_to, \'%Y-%m-%d\')'),
+ ]
+ ]
+ )
+ ->andWhere([
+ 'export_import_table.entity' => 'city_store'
+ ])
+ ->andFilterWhere([
+ 'store_dynamic.value_int' => $cluster_id,
+ 'city_store.id' => $store_id
+ ])
+ ->andWhere([
+ 'DATE_FORMAT(write_offs.date, \'%Y-%m-%d\')' => $date
+ ])
+ ->andWhere([
+ 'write_offs.type' => 'Брак'
+ ])
+ ->orderBy([
+ 'store_dynamic.value_int' => SORT_ASC,
+ 'city_store.id' => SORT_ASC,
+ 'write_offs.date' => SORT_ASC,
+ ]);
+
+ $dataProvider = new ArrayDataProvider([
+ 'allModels' => $query_write_offs->asArray()->all()
+ ]);
+
+ return $this->render('write-offs', [
+ 'dataProvider' => $dataProvider,
+ 'date' => $date
+ ]);
+ }
+
+}
\ No newline at end of file