]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Правки пересчета
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 1 Jul 2025 13:33:48 +0000 (16:33 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 1 Jul 2025 13:33:48 +0000 (16:33 +0300)
erp24/commands/CronController.php
erp24/controllers/CategoryPlanController.php
erp24/views/category-plan/index.php
erp24/web/js/category-plan/index.js

index e1eb5e25b76e196a95928a8dfc773b5b9ee7a270..6111b05feb007457e1bd5f9bf71a0735add8e5ed 100644 (file)
@@ -1780,7 +1780,10 @@ class CronController extends Controller
             $log->month = (int)$task['month'];
             $log->active = 1;
             $log->date_start = date('Y-m-d H:i:s');
-            $log->save(false);
+            if (!$log->save()) {
+                Yii::error(json_encode($log->getErrors(), JSON_UNESCAPED_UNICODE));
+                LogService::apiErrorLog(json_encode(["error_id" => 8, "error" => $log->getErrors()], JSON_UNESCAPED_UNICODE));
+            }
 
             $service = new AutoPlannogrammaService();
             $year = (int)$task['year'];
@@ -1906,7 +1909,10 @@ class CronController extends Controller
                 $log->active = 0;
                 $log->date_finish = date('Y-m-d H:i:s');
                 $log->status = 1;
-                $log->save(false);
+                if (!$log->save()) {
+                    Yii::error(json_encode($log->getErrors(), JSON_UNESCAPED_UNICODE));
+                    LogService::apiErrorLog(json_encode(["error_id" => 8, "error" => $log->getErrors()], JSON_UNESCAPED_UNICODE));
+                }
 
                 $this->stdout("Расчет для магазина {$storeId} закончен\n");
                 return ExitCode::OK;
@@ -1923,8 +1929,11 @@ class CronController extends Controller
                 $log->active = 0;
                 $log->date_finish = date('Y-m-d H:i:s');
                 $log->status = 2;
-                $log->save(false);
-
+                if (!$log->save()) {
+                    Yii::error(json_encode($log->getErrors(), JSON_UNESCAPED_UNICODE));
+                    LogService::apiErrorLog(json_encode(["error_id" => 8, "error" => $log->getErrors()], JSON_UNESCAPED_UNICODE));
+                }
+                Yii::$app->cache->delete("apRecalculateTask");
                 $this->stderr("Ошибка в ходе расчета: {$e->getMessage()}\n");
                 return ExitCode::UNSPECIFIED_ERROR;
             }
index 0a5f3648ee7dfee16224ea609b56d1270eb7397d..bc9dc24cc3f1c781e979e7d1e01fa05eaa48209a 100644 (file)
@@ -18,6 +18,7 @@ use yii_app\records\ExportImportTable;
 use yii_app\records\Products1cNomenclature;
 use yii_app\records\Sales;
 use yii_app\records\SalesWriteOffsPlan;
+use yii_app\records\ScriptLauncherLog;
 use yii_app\records\StoreDynamic;
 use yii_app\records\WriteOffs;
 use yii_app\records\WriteOffsErp;
@@ -25,404 +26,8 @@ use yii_app\services\AutoPlannogrammaService;
 use yii_app\services\StorePlanService;
 
 class CategoryPlanController extends Controller {
-    public function actionIndex()
-    {
-        $model = DynamicModel::validateData([
-            'year' => date('Y'),
-            'month' => date('m'),
-            'store_id' => null,
-            'city_id' => null,
-            'region_id' => null,
-            'raion_id' => null,
-            'store_type_id' => null,
-            'territory_manager_id' => null,
-            'kshf_id' => null,
-        ], [
-            [[
-                'year', 'month', 'store_id', 'city_id', 'region_id', 'raion_id', 'store_type_id',
-                'territory_manager_id', 'kshf_id'
-            ], 'safe']
-        ]);
-
-        $model->load(Yii::$app->request->get());
-
-        $service = new AutoPlannogrammaService();
-        $isEditable = date($model->year . '-' . $model->month . '-d') > date('Y-m-d') && (
-            (date('d') < 27) || (date('Y-m-d', strtotime('-1 month', strtotime(date($model->year . '-' . $model->month . '-d')))) > date('Y-m-d')));
-
-        $categoryPlan = CategoryPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->indexBy('category')->asArray()->all();
-        $types = [];
-        $table = [];
-        $tableOnline = [];
-        $tableWriteOffs = [];
-        $years = [];
-        for ($i = 3; $i >= 0; $i--) {
-            $year = date("Y") - $i;
-            $years [$year] = $year;
-        }
-        $stores = ArrayHelper::map(CityStore::find()->andWhere(['visible' => '1'])->all(), 'id', 'name');
-        $salesWriteOffsPlan = SalesWriteOffsPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->one();
-        /////////////////////////// CHAT GPT STUFF ///////////////////////////////////
-        //var_dump(Yii::$app->request->get()); die();
-        if (
-            $model->year
-            && $model->month
-            && $model->store_id
-        ) {
-            if (Yii::$app->request->get('delete') === '1'
-            ) {
-                $count = Yii::$app->db
-                    ->createCommand()
-                    ->delete('erp24.category_plan', [
-                        'year' => $model->year,
-                        'month' => $model->month,
-                        'store_id' => $model->store_id,
-                    ])
-                    ->execute();
-
-                Yii::$app->session->setFlash(
-                    $count ? 'success' : 'info',
-                    $count
-                        ? "Удалено {$count} записей."
-                        : 'Ничего не удалено.'
-                );
 
-
-                $params = [
-                    'DynamicModel' => $model->attributes,
-                ];
-
-                $params['DynamicModel'] = array_filter($params['DynamicModel'], function($v) {
-                    return $v !== null && $v !== '';
-                });
-
-                return $this->redirect(array_merge(
-                    ['index'],
-                    $params
-                ));
-
-            }
-            $currentDate = new \DateTime(date($model->year . '-' . $model->month . '-01'));
-
-            $startDate = (clone $currentDate)->modify('-4 months')->modify('first day of this month');
-
-            $endDate = (clone $startDate)->modify('+2 months')->modify('last day of this month');
-
-            $date_start = $startDate->format('Y-m-d');
-            $date_end = $endDate->format('Y-m-d');
-
-            $sales = Sales::find()->alias('s')->select([
-                "COUNT(*) as cnt",
-                "SUM(CASE WHEN operation='Продажа' THEN sp.summ ELSE (CASE WHEN operation='Возврат' THEN -sp.summ ELSE 0 END) END) as total",
-                "s.store_id",
-                "p1cn.category as type",
-                "TO_CHAR(s.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('sales_products sp', 's.id = sp.check_id')
-                ->leftJoin('products_1c p1c', 'p1c.id = sp.product_id')
-                ->leftJoin('products_1c_nomenclature p1cn', 'p1cn.id = sp.product_id')
-                ->where(['between', 's.date', $date_start, $date_end])
-                ->andWhere(['order_id' => ['', '0']])
-                ->andWhere(['p1c.components' => ''])
-                ->andWhere(['not in', 'p1cn.category', ['', 'букет', 'сборка', 'сервис']])
-                ->andWhere(['s.store_id' => $model->store_id])
-                ->groupBy([
-                    's.store_id',
-                    "TO_CHAR(s.date, 'YYYY-MM')",
-                    "p1cn.category"
-                ])
-                ->orderBy(['month' => SORT_ASC, 'type' => SORT_ASC])
-                ->asArray()
-                ->all();
-
-            $salesMatrixOffline = Sales::find()->alias('s')->select([
-                "COUNT(*) as cnt",
-                "SUM(CASE WHEN operation='Продажа' THEN sp.summ ELSE (CASE WHEN operation='Возврат' THEN -sp.summ ELSE 0 END) END) as total",
-                "s.store_id",
-                "p1c.type as type",
-                "TO_CHAR(s.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('sales_products sp', 's.id = sp.check_id')
-                ->leftJoin('products_1c p1c', 'p1c.id = sp.product_id')
-                ->where(['between', 's.date', $date_start, $date_end])
-                ->andWhere(['order_id' => ['', '0']])
-                ->andWhere(['p1c.type' => 'Матрица'])
-                ->andWhere(['s.store_id' => $model->store_id])
-                ->groupBy([
-                    's.store_id',
-                    "TO_CHAR(s.date, 'YYYY-MM')",
-                    "p1c.type"
-                ])
-                ->orderBy(['month' => SORT_ASC, 'type' => SORT_ASC])
-                ->asArray()
-                ->all();
-
-
-            $compoundSalesData = [];
-            for ($i = 0; $i < 3; $i++) {
-                $dateToStart = (clone $startDate)->modify("+$i months");
-                $compoundSalesYear = $dateToStart->format('Y');
-                $compoundSalesMonth = $dateToStart->format('m');
-                $compoundSales = $service->getProductsComponentsInCategory($model->store_id, $compoundSalesMonth, $compoundSalesYear);
-                $offline = [];
-                $online = [];
-                foreach ($compoundSales as $compoundSale) {
-                    if (in_array($compoundSale['order_id'], ['', '0'], true)) {
-                        $offline[] = $compoundSale;
-                    } else {
-                        $online[] = $compoundSale;
-                    }
-                }
-                $dateKey = $compoundSalesYear . '-' . $compoundSalesMonth;
-                $offlineCompoundSum = $service->sumProductsComponentsByGroup($offline, AutoPlannogrammaService::TYPE_SALES);
-                $onlineCompoundSum = $service->sumProductsComponentsByGroup($online, AutoPlannogrammaService::TYPE_SALES);
-
-                $compoundSalesData['offline'][$dateKey] = $offlineCompoundSum;
-                $compoundSalesData['online'][$dateKey] = $onlineCompoundSum;
-
-
-            }
-            //var_dump($compoundSalesData); die();
-
-
-            $mnths = [];
-            foreach ($sales as $sale) {
-                $mnths[$sale['month']] = 1;
-                $types[$sale['type']] = 1;
-            }
-            $mnths = array_keys($mnths);
-
-            sort($mnths);
-
-            $weights = [];
-            foreach ($mnths as $ind => $month) {
-                $weights[$month] = $ind + 1;
-            }
-
-            foreach ($sales as $sale) {
-                $table[$sale['store_id']][$sale['type']] = ($table[$sale['store_id']][$sale['type']] ?? 0) + $weights[$sale['month']] * $sale['total'] ;
-            }
-            foreach ($salesMatrixOffline as $saleMatrix) {
-                $types[$saleMatrix['type']] = 1;
-                $table[$saleMatrix['store_id']][$saleMatrix['type']] = ($table[$saleMatrix['store_id']][$saleMatrix['type']] ?? 0) + $weights[$saleMatrix['month']] * $saleMatrix['total'] ;
-            }
-            //var_dump($table); die();
-            foreach ($compoundSalesData['offline'] as $monthKey => $categories) {
-                $w = $weights[$monthKey] ?? 0;
-                foreach ($categories as $item) {
-                    $store = $item['store_id'];
-                    $type = $item['category'];
-                    $sum = (float)$item['sum'];
-                    $types[$item['category']] = 1;
-                    $table[$store][$type] = ($table[$store][$type] ?? 0)
-                        + $w * $sum ;
-                }
-            }
-
-            $offlinePlannedSales = self::calculatePlannedSales($table, $salesWriteOffsPlan->offline_sales_plan);
-
-            $salesOnline = Sales::find()->alias('s')->select([
-                "COUNT(*) as cnt",
-                "SUM(CASE WHEN operation='Продажа' THEN sp.summ ELSE (CASE WHEN operation='Возврат' THEN -sp.summ ELSE 0 END) END) as total",
-                "s.store_id",
-                "p1cn.category as type",
-                "TO_CHAR(s.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('sales_products sp', 's.id = sp.check_id')
-                ->leftJoin('products_1c p1c', 'p1c.id = sp.product_id')
-                ->leftJoin('products_1c_nomenclature p1cn', 'p1cn.id = sp.product_id')
-                ->where(['between', 's.date', $date_start, $date_end])
-                ->andWhere(['not in', 'order_id', ['', '0']])
-                ->andWhere(['s.store_id' => $model->store_id])
-                ->andWhere(['p1c.components' => ''])
-                ->andWhere(['not in', 'p1cn.category', ['', 'букет', 'сборка', 'сервис']])
-                ->groupBy([
-                    's.store_id',
-                    "TO_CHAR(s.date, 'YYYY-MM')",
-                    "p1cn.category"
-                ])
-                ->orderBy(['month' => SORT_ASC, 'type' => SORT_ASC])
-                ->asArray()
-                ->all();
-
-
-            $salesMatrixOnline = Sales::find()->alias('s')->select([
-                "COUNT(*) as cnt",
-                "SUM(CASE WHEN operation='Продажа' THEN sp.summ ELSE (CASE WHEN operation='Возврат' THEN -sp.summ ELSE 0 END) END) as total",
-                "s.store_id",
-                "p1c.type as type",
-                "TO_CHAR(s.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('sales_products sp', 's.id = sp.check_id')
-                ->leftJoin('products_1c p1c', 'p1c.id = sp.product_id')
-                ->where(['between', 's.date', $date_start, $date_end])
-                ->andWhere(['not in', 'order_id', ['', '0']])
-                ->andWhere(['p1c.type' => 'Матрица'])
-                ->andWhere(['s.store_id' => $model->store_id])
-                ->groupBy([
-                    's.store_id',
-                    "TO_CHAR(s.date, 'YYYY-MM')",
-                    "p1c.type"
-                ])
-                ->orderBy(['month' => SORT_ASC, 'type' => SORT_ASC])
-                ->asArray()
-                ->all();
-
-
-            foreach ($salesOnline as $sale) {
-                $types[$sale['type']] = 1;
-                $tableOnline[$sale['store_id']][$sale['type']] = ($tableOnline[$sale['store_id']][$sale['type']] ?? 0) + $weights[$sale['month']] * $sale['total'] ;
-            }
-            foreach ($salesMatrixOnline as $saleMatrix) {
-                $types[$saleMatrix['type']] = 1;
-                $tableOnline[$saleMatrix['store_id']][$saleMatrix['type']] = ($tableOnline[$saleMatrix['store_id']][$saleMatrix['type']] ?? 0) + $weights[$saleMatrix['month']] * $saleMatrix['total'] ;
-            }
-
-            foreach ($compoundSalesData['online'] as $monthKey => $categories) {
-                $w = $weights[$monthKey] ?? 0;
-                foreach ($categories as $item) {
-                    $store = $item['store_id'];
-                    $type = $item['category'];
-                    $sum = (float)$item['sum'];
-                    $types[$item['category']] = 1;
-                    $tableOnline[$store][$type] = ($tableOnline[$store][$type] ?? 0)
-                        + $w * $sum ;
-                }
-            }
-
-            $onlinePlannedSales = self::calculatePlannedSales($tableOnline, $salesWriteOffsPlan->online_sales_shop_plan);
-
-
-            $eit = ExportImportTable::find()->where(['entity' => 'city_store', 'export_id' => 1, 'entity_id' => $model->store_id])->one();
-            $store_id = $eit->export_val ?? '';
-            $writeOffs = WriteOffs::find()->alias('wo')->select([
-                'sum(wop.summ) as total',
-                "p1cn.category as p1ctype",
-                'ex.entity_id AS store_id',
-                "TO_CHAR(wo.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('write_offs_products wop', 'wop.write_offs_id = wo.id')
-                ->leftJoin('products_1c p1c', 'p1c.id = wop.product_id')
-                ->leftJoin('products_1c_nomenclature p1cn', 'p1cn.id = wop.product_id')
-                ->leftJoin('export_import_table ex', 'ex.export_val = wo.store_id')
-                ->where(['between', 'wo.date', $date_start, $date_end])
-                ->andWhere(['wo.type' => WriteOffsErp::WRITE_OFFS_TYPE_BRAK])
-                ->andWhere(['p1c.components' => ''])
-                ->andWhere(['not in', 'p1cn.category', ['', 'букет', 'сборка', 'сервис']])
-                ->andWhere(['wo.store_id' => $store_id])
-                ->groupBy([
-                    "month",
-                    'ex.entity_id',
-                    "p1cn.category"
-                ])
-                ->asArray()->all();
-
-            $writeOffsMatrix = WriteOffs::find()->alias('wo')->select([
-                'sum(wop.summ) as total',
-                'ex.entity_id AS store_id',
-                "p1c.type as p1ctype",
-                "TO_CHAR(wo.date, 'YYYY-MM') as month"
-            ])
-                ->leftJoin('write_offs_products wop', 'wop.write_offs_id = wo.id')
-                ->leftJoin('products_1c p1c', 'p1c.id = wop.product_id')
-                ->leftJoin('products_1c_nomenclature p1cn', 'p1cn.id = wop.product_id')
-                ->leftJoin('export_import_table ex', 'ex.export_val = wo.store_id')
-                ->where(['between', 'wo.date', $date_start, $date_end])
-                ->andWhere(['wo.type' => WriteOffsErp::WRITE_OFFS_TYPE_BRAK])
-                ->andWhere(['p1c.type' => 'Матрица'])
-                ->andWhere(['wo.store_id' => $store_id])
-                ->groupBy([
-                    "month",
-                    'ex.entity_id',
-                    "p1c.type"
-                ])
-                ->asArray()->all();
-
-
-            $compoundWriteOffsData = [];
-            for ($i = 0; $i < 3; $i++) {
-
-                $dateToStartWriteOffs = (clone $startDate)->modify("+$i months");
-                $compoundSalesYear = $dateToStartWriteOffs->format('Y');
-                $compoundSalesMonth = $dateToStartWriteOffs->format('m');
-                $compoundWriteOffs = $service->getProductsComponentsInCategory($model->store_id, $compoundSalesMonth, $compoundSalesYear, AutoPlannogrammaService::TYPE_WRITE_OFFS);
-
-                $writeoffsCompoundSum = $service->sumProductsComponentsByGroup($compoundWriteOffs, AutoPlannogrammaService::TYPE_WRITE_OFFS);
-
-                $dateKey = $compoundSalesYear . '-' . $compoundSalesMonth;
-                $compoundWriteOffsData[$dateKey] = $writeoffsCompoundSum;
-            }
-
-
-            foreach ($writeOffs as $writeoff) {
-                $types[$writeoff['p1ctype']] = 1;
-                $tableWriteOffs[$writeoff['store_id']][$writeoff['p1ctype']] = ($tableWriteOffs[$writeoff['store_id']][$writeoff['p1ctype']] ?? 0) + $weights[$writeoff['month']] * $writeoff['total'];
-            }
-
-            foreach ($writeOffsMatrix as $writeOffMatrix) {
-                $types[$writeOffMatrix['p1ctype']] = 1;
-                $tableWriteOffs[$writeOffMatrix['store_id']][$writeOffMatrix['p1ctype']] = ($tableWriteOffs[$writeOffMatrix['store_id']][$writeOffMatrix['p1ctype']] ?? 0) + $weights[$writeOffMatrix['month']] * $writeOffMatrix['total'];
-            }
-
-            foreach ($compoundWriteOffsData as $monthKey => $categories) {
-                $w = $weights[$monthKey] ?? 0;
-                foreach ($categories as $item) {
-                    $store = $item['store_id'];
-                    $type = $item['category'];
-                    $sum = (float)$item['sum'];
-                    $types[$item['category']] = 1;
-                    $tableWriteOffs[$store][$type] = ($tableWriteOffs[$store][$type] ?? 0)
-                        + $w * $sum ;
-                }
-            }
-            $plannedWriteOffs = self::calculatePlannedSales($tableWriteOffs, $salesWriteOffsPlan->write_offs_plan);
-            $types = array_keys($types);
-            /////////////////////////////////////////////////////////////////////////////////////
-
-            foreach ($types as $type) {
-                if (!empty($type) && !isset($categoryPlan[$type])) {
-                    $categoryPlanNew = new CategoryPlan;
-                    $categoryPlanNew->year = $model->year;
-                    $categoryPlanNew->month = $model->month;
-                    $categoryPlanNew->store_id = $model->store_id;
-                    $categoryPlanNew->category = $type;
-                    $categoryPlanNew->offline = $offlinePlannedSales[$model->store_id][$type] ?? 0;
-                    $categoryPlanNew->internet_shop = $onlinePlannedSales[$model->store_id][$type] ?? 0;
-                    $categoryPlanNew->marketplace = 0;
-                    $categoryPlanNew->write_offs = $plannedWriteOffs[$model->store_id][$type] ?? 0;
-                    $categoryPlanNew->created_at = date('Y-m-d HH:i:s');
-                    $categoryPlanNew->updated_at = date('Y-m-d HH:i:s');
-                    $categoryPlanNew->created_by = Yii::$app->user->id;
-                    $categoryPlanNew->updated_by = Yii::$app->user->id;
-                    $categoryPlanNew->save();
-                    if ($categoryPlanNew->getErrors()) {
-                        throw new Exception(Json::encode($categoryPlanNew->getErrors()));
-                    }
-                }
-            }
-
-            $categoryPlan = CategoryPlan::find()->where(['year' => $model->year, 'month' => $model->month, 'store_id' => $model->store_id])->indexBy('category')->asArray()->all();
-
-
-            $order = [
-                'Срезка' => 1,
-                'Сухоцветы' => 2,
-                'Горшечные_растения' => 3,
-                'Сопутствующие_товары' => 4,
-                'Упаковка' => 5,
-                'Матрица' => 6,
-            ];
-
-            usort($types, function ($a, $b) use ($order) {
-                return ($order[$a] ?? 999) <=> ($order[$b] ?? 999);
-            });
-
-        }
-
-        return $this->render('index', compact('model', 'years', 'stores', 'table', 'tableOnline',
-            'tableWriteOffs', 'types', 'salesWriteOffsPlan', 'isEditable', 'categoryPlan'));
-    }
-    public function actionNew()
+    public function actionIndex()
     {
         $model = DynamicModel::validateData([
             'year' => date('Y'),
@@ -483,20 +88,16 @@ class CategoryPlanController extends Controller {
                         ? "Удалено {$count} записей."
                         : 'Ничего не удалено.'
                 );
-                Yii::$app->cache->set('needRecalc', time(), 3600);
-
-                $params = [
-                    'DynamicModel' => $model->attributes,
-                ];
-
-                $params['DynamicModel'] = array_filter($params['DynamicModel'], function($v) {
-                    return $v !== null && $v !== '';
-                });
-
-                return $this->redirect(array_merge(
-                    ['new'],
-                    $params
-                ));
+                Yii::$app->cache->set('needRecalc', 'Recalc', 3600);
+                Yii::$app->cache->delete("apRecalculateTask");
+                if (Yii::$app->request->isAjax) {
+                    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+                    return [
+                        'status' => 'ok',
+                        'message' => "Удалено {$count} записей.",
+                        'data' => Yii::$app->cache->get('needRecalc')
+                    ];
+                }
 
             }
 
@@ -650,12 +251,29 @@ class CategoryPlanController extends Controller {
                     $categoryPlanNew->updated_at = date('Y-m-d HH:i:s');
                     $categoryPlanNew->created_by = Yii::$app->user->id;
                     $categoryPlanNew->updated_by = Yii::$app->user->id;
-                    $categoryPlanNew->save();
-                    if ($categoryPlanNew->getErrors()) {
+                    if ( $categoryPlanNew->save()) {
+                        $recalcFlag = Yii::$app->cache->get('needRecalc');
+                        if ($recalcFlag) {
+                            $taskName = "apRecalculateTask";
+
+                            $cacheValue = [
+                                'taskName'  => $taskName,
+                                'year'      => $model->year,
+                                'month'     => $model->month,
+                                'storeId'   => $model->store_id,
+                                'status'    => 'pending',
+                                'startTime' => date('Y-m-d H:i:s'),
+                                'progress'  => 0,
+                                'error'     => null
+                            ];
+                            Yii::$app->cache->set($taskName, $cacheValue, 3600);
+                            Yii::$app->cache->delete('needRecalc');
+                        }
+                    } else {
                         throw new Exception(Json::encode($categoryPlanNew->getErrors()));
                     }
 
-                    $recalcFlag = Yii::$app->cache->get('needRecalc');
+
                 }
             }
 
@@ -677,7 +295,7 @@ class CategoryPlanController extends Controller {
 
         }
 
-        return $this->render('new', compact('model', 'years', 'stores', 'table', 'tableOnline',
+        return $this->render('index', compact('model', 'years', 'stores', 'table', 'tableOnline',
             'tableWriteOffs', 'types', 'salesWriteOffsPlan', 'isEditable', 'categoryPlan'));
     }
 
@@ -972,28 +590,42 @@ class CategoryPlanController extends Controller {
         $year  = (int)Yii::$app->request->get('year');
         $month = (int)Yii::$app->request->get('month');
         $store = (int)Yii::$app->request->get('store_id');
-        $taskName = "apRecalculateTask";
-
-        $cacheValue = [
-            'taskName'  => $taskName,
-            'year'      => $year,
-            'month'     => $month,
-            'storeId'   => $store,
-            'status'    => 'pending',
-            'startTime' => date('Y-m-d H:i:s'),
-            'progress'  => 0,
-            'error'     => null
-        ];
-        Yii::$app->cache->set($taskName, $cacheValue, 3600);
-
-        return $this->asJson(['status' => 'started', 'data' => Yii::$app->cache->get('apRecalculateTask') ]);
+        $scriptLauncherLog = ScriptLauncherLog::find()
+            ->andWhere(['name' => "taskApRecalculate"])
+            ->orderBy(['created_at' => SORT_DESC])
+            ->asArray()
+            ->limit(1)
+            ->one();
+        if ($scriptLauncherLog && $scriptLauncherLog['active'] == 1) {
+            return $this->asJson(['status' => 'running' ]);
+        } else {
+            $taskName = "apRecalculateTask";
+
+            $cacheValue = [
+                'taskName'  => $taskName,
+                'year'      => $year,
+                'month'     => $month,
+                'storeId'   => $store,
+                'status'    => 'pending',
+                'startTime' => date('Y-m-d H:i:s'),
+                'progress'  => 0,
+                'error'     => null
+            ];
+            Yii::$app->cache->set($taskName, $cacheValue, 3600);
+
+            return $this->asJson(['status' => 'started', 'data' => Yii::$app->cache->get('apRecalculateTask') ]);
+        }
+
     }
 
     public function actionCheckTask()
     {
         $task = Yii::$app->cache->get('apRecalculateTask');
-
+        if ($task && $task['status'] === 'done') {
+            Yii::$app->cache->delete("apRecalculateTask");
+        }
         if (!$task) {
+
             return $this->asJson(['status' => 'not_found']);
         }
 
index a7dc4de86b599380c67b5fa79e9139774ed89d18..9cdcc31ecdef9063cf97b55b022e77aac4e3b142 100644 (file)
@@ -38,19 +38,19 @@ input[readonly] {
 <div class="categoryPlanIndex m-5">
 
     <h1>План по категориям</h1>
-  <p><?= Html::a(
-          '📖 Документация',
-          Url::to(
-              ['wiki/show-doc', 'returnUrl' => Yii::$app->request->url]
-          ),
-          ['class' => 'ms-3 mb-3 pb-3', 'target' => '_blank', 'title' => 'Открыть документацию']
-      ) ?></p>
+    <p><?= Html::a(
+            '📖 Документация',
+            Url::to(
+                ['wiki/show-doc', 'returnUrl' => Yii::$app->request->url]
+            ),
+            ['class' => 'ms-3 mb-3 pb-3', 'target' => '_blank', 'title' => 'Открыть документацию']
+        ) ?></p>
 
 
     <?php $form = ActiveForm::begin([
         'id' => 'filter-form',
         'method' => 'GET',
-        'action' => '/category-plan'
+        'action' => '/category-plan/index'
     ]) ?>
 
     <div class="row">
@@ -159,10 +159,22 @@ input[readonly] {
                 <div class="col-1"></div>
                 <div class="col-11">
                     <?= Html::submitButton('Применить', ['class' => 'btn btn-secondary'])?>
-                    <?php if ($model->month && $model->year && $model->store_id) { ?>
-                    <?= Html::submitButton('Вернуть автоплан', [
-                        'class' => 'btn btn-danger ms-2',
+
+                </div>
+            </div>
+        </div>
+    </div>
+    <?php ActiveForm::end() ?>
+
+    <?php if (isset($model->store_id)): ?>
+        <div class="row">
+            <div class="col-4">
+                <h1><?= $stores[$model->store_id]?></h1>
+                <?php if ($model->month && $model->year && $model->store_id) { ?>
+                    <?= Html::button('Вернуть автоплан', [
+                        'class' => 'btn btn-danger m-2',
                         'name'  => 'delete',
+                        'id' => 'delete',
                         'value' => 1,
                         'data'  => [
                             'confirm' => 'Вы уверены, что хотите вернуть автоплан за '
@@ -170,8 +182,9 @@ input[readonly] {
                         ],
                     ])
                     ?>
-                    <?= Html::submitButton('Пересчитать автопланограмму', [
-                        'class' => 'btn btn-success ms-2',
+
+                    <?= Html::button('Пересчитать автопланограмму', [
+                        'class' => 'btn btn-success m-2',
                         'disabled' => true,
                         'id' => 'rebuild',
                         'name'  => 'rebuild',
@@ -182,36 +195,28 @@ input[readonly] {
                         ],
                     ])
                     ?>
-                    <?php } ?>
-                </div>
-            </div>
-        </div>
-    </div>
-    <?php ActiveForm::end() ?>
-
-    <?php if (isset($model->store_id)): ?>
-        <div class="row">
-            <div class="col-4">
-                <h1><?= $stores[$model->store_id]?></h1>
+                <?php } ?>
+                <div id="changes-count"></div>
+                <div id="changes" style="display:none;"></div>
             </div>
         </div>
         <?php if (isset($salesWriteOffsPlan)): ?>
-        <div class="table-responsive" style="max-width: 1285px;">
-            <table id="categoryPlan" style="width:100%">
-                <?php
-                $offline_sale = $salesWriteOffsPlan->offline_sales_plan;
-                $online_sale = $salesWriteOffsPlan->online_sales_shop_plan;
-                $write_offs = $salesWriteOffsPlan->write_offs_plan;
-                ?>
-                <thead>
+            <div class="table-responsive" style="max-width: 1285px;">
+                <table id="categoryPlan" style="width:100%">
+                    <?php
+                    $offline_sale = $salesWriteOffsPlan->offline_sales_plan;
+                    $online_sale = $salesWriteOffsPlan->online_sales_shop_plan;
+                    $write_offs = $salesWriteOffsPlan->write_offs_plan;
+                    ?>
+                    <thead>
                     <tr><th rowspan="4" class="text-center align-middle border">Категории</th><th colspan="4" class="text-center border">План продаж</th><th colspan="2" class="text-center border">Списания</th></tr>
                     <tr><th colspan="2" class="text-center border">Оффлайн</th><th colspan="2" class="text-center border">Интернет-Магазин</th><th colspan="2" class="text-center border">Списания</th></tr>
                     <tr><th colspan="2" class="text-center border" data-value="<?= $offline_sale ?>"><?= number_format($offline_sale, 0, '.', ' ') ?></th>
                         <th colspan="2" class="text-center border" data-value="<?= $online_sale ?>"><?= number_format($online_sale, 0, '.', ' ') ?></th>
                         <th colspan="2" class="text-center border" data-value="<?= $write_offs ?>"><?= number_format($write_offs, 0, '.', ' ') ?></th></tr>
                     <tr><th class="text-center border">%</th><th class="text-center border">Сумма</th><th class="text-center border">%</th><th class="text-center border">Cумма</th><th class="text-center border">%</th><th class="text-center border">Cумма</th></tr>
-                </thead>
-                <tbody>
+                    </thead>
+                    <tbody>
                     <?php foreach ($types as $type): ?>
                         <tr>
                             <th data-type><?= $type ?></th>
@@ -236,9 +241,9 @@ input[readonly] {
                             <td data-writeoffs-type="<?= $type ?>"><?= Html::textInput('write_offs', number_format($categoryPlan[$type]['write_offs'], 0, '.', ''), ['type' => 'number',  'readonly' => true, ]) ?></td>
                         </tr>
                     <?php endforeach; ?>
-                </tbody>
-            </table>
-        </div>
+                    </tbody>
+                </table>
+            </div>
         <?php else: ?>
             <span class="text-lightpink-red font-weight-bold">
                 Не задан план по магазину. Чтобы задать план пройдите на страницу
index c7aef7f7d3e160346e2c8c36a1b3ea3671a7a934..38b02a90e159ade8f35db61ecf8e91eb24a6cff6 100644 (file)
@@ -114,17 +114,28 @@ function updateChangesLog(store_id) {
         changes[store_id] = {};
     }
     console.log(changes);
-    const count = Object.keys(changes[store_id]).length;
+    let count = 0;
     let listItems = '';
     Object.entries(changes[store_id]).forEach(([category, values]) => {
-        if (values.offline !== undefined)
+        if (values.offline !== undefined) {
             listItems += `<li>${category} - ${values.offline}</li>`;
-        if (values.internet_shop !== undefined)
+            count++;
+        }
+
+        if (values.internet_shop !== undefined) {
             listItems += `<li>${category} - ${values.internet_shop}</li>`;
-        if (values.write_offs !== undefined)
+            count++;
+        }
+
+        if (values.write_offs !== undefined) {
             listItems += `<li>${category} - ${values.write_offs}</li>`;
-    });
+            count++;
+        }
 
+    });
+    $('#changes-hint').remove();
+    $('#changes').after('<div id="changes-hint" style="color:red; margin-top:10px;">После внесения всех изменений нажмите на кнопку\n' +
+        '"Пересчитать автопланограмму"</div>');
     changesBox.html(`<ul>${listItems}</ul>`).hide();
     changesCount.html(`Были внесены изменения (число изменений) - ${count} <button id="show-changes" class="btn btn-link">Подробнее</button>`);
 
@@ -148,16 +159,11 @@ $(document).ready(() => {
     if (store_id && changes[store_id]) {
         updateChangesLog(store_id);
         $('#rebuild').prop('disabled', false);
-        $('#changes-hint').remove();
-        $('#changes').after('<div id="changes-hint" style="color:red; margin-top:10px;">После внесения всех изменений нажмите на кнопку\n' +
-            '"Пересчитать автопланограмму"</div>');
+
     }
 
     $('#delete').on('click', function (event) {
         event.preventDefault();
-        localStorage.removeItem('planChanges');
-
-
         const year = $('#dynamicmodel-year').val();
         const month = $('#dynamicmodel-month').val();
         const store_id = $('#selected-store').val();
@@ -168,12 +174,18 @@ $(document).ready(() => {
             'DynamicModel[store_id]': store_id,
             'delete': 1
         };
-
+        $('#rebuild').prop('disabled', true).text('Пересчёт запущен...');
+        $('#delete').prop('disabled', true);
         $.ajax({
-            url: '/category-plan/new',
+            url: '/category-plan/index',
             method: 'GET',
             data: params,
             success: function (response) {
+                const message = response.message;
+                console.log(response.data);
+                alert(`План удалён. ${message} Страница перезагрузится, чтобы пересчитать автоплан`);
+                localStorage.removeItem('planChanges');
+                location.reload();
             },
             error: function () {
                 alert('Ошибка при удалении автоплана.');
@@ -183,9 +195,9 @@ $(document).ready(() => {
 
     $('#rebuild').on('click', function (event) {
         event.preventDefault();
-        localStorage.removeItem('planChanges');
-        $('#rebuild').prop('disabled', true).text('Пересчёт запущен...');
 
+        $('#rebuild').prop('disabled', true).text('Пересчёт запущен...');
+        $('#delete').prop('disabled', true);
         $.ajax({
             url: '/category-plan/rebuild',
             type: 'GET',
@@ -195,9 +207,16 @@ $(document).ready(() => {
                 store_id: store_id
             },
             success: function (data) {
-                startTaskPolling();
-                $('#rebuild').prop('disabled', true);
-                console.log(data.data);
+                if (data.status == 'running') {
+                    alert('Другая задача запущена!');
+                    return;
+                }
+                if (data.status == 'started') {
+                    startTaskPolling();
+                    $('#rebuild').prop('disabled', true);
+                    console.log(data.data);
+                }
+
             },
             error: function () {
                 alert('Ошибка запуска пересчёта!');
@@ -205,30 +224,46 @@ $(document).ready(() => {
             }
         });
     });
+    startTaskPolling();
 });
 
 let taskPollInterval = null;
 
 function startTaskPolling() {
     if (taskPollInterval) return;
-
+    console.log('check-task');
     taskPollInterval = setInterval(() => {
         $.ajax({
             url: '/category-plan/check-task',
             type: 'GET',
             dataType: 'json',
             success: function (data) {
-                if (data.status === 'done' || data.status === 'error') {
+                console.log(data.status);
+                if (data.status === 'running' || data.status === 'pending') {
+                    $('#rebuild').prop('disabled', true).text('Пересчёт запущен...');
+                    $('#delete').prop('disabled', true);
+                }
+                if (data.status === 'done') {
                     clearInterval(taskPollInterval);
                     taskPollInterval = null;
+                    localStorage.removeItem('planChanges');
                     $('#rebuild').prop('disabled', false).text('Пересчитать автопланограмму');
-
+                    $('#delete').prop('disabled', false);
                     if (data.status === 'done') {
+                        $('#changes-hint').remove();
+                        $('#changes').hide();
                         alert('Задача успешно завершена');
                     } else {
                         alert('Задача завершилась с ошибкой: ' + (data.error || ''));
                     }
                 }
+                if (data.status === 'error') {
+                    clearInterval(taskPollInterval);
+                    taskPollInterval = null;
+                    $('#rebuild').prop('disabled', false).text('Пересчитать автопланограмму');
+                    $('#delete').prop('disabled', false);
+                    alert('Задача завершилась с ошибкой: ' + (data.error || ''));
+                }
             }
         });
     }, 3000);