]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Добавление типов матрицы
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 16 May 2025 10:07:59 +0000 (13:07 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 16 May 2025 10:07:59 +0000 (13:07 +0300)
erp24/controllers/BouquetController.php
erp24/migrations/m250514_143555_create_matrix_bouquet_forecast_table.php
erp24/records/MatrixBouquetForecast.php
erp24/services/StorePlanService.php
erp24/views/bouquet/get-guid-bouquet.php
erp24/views/bouquet/month-goal-forecast.php

index d76944417af49272840405141debaf594973b5f9..79d3846760cdaa28afaeca05e87ddc85906fa36e 100644 (file)
@@ -308,10 +308,12 @@ class BouquetController extends Controller
         $month = $post['DynamicModel']['month'] ?? 5;
         $year = $post['DynamicModel']['year'] ?? 2025;
         $storeId = $post['DynamicModel']['storeId'] ?? 2;
+        $matrix = $post['DynamicModel']['matrix'] ?? [];
 
         $model = DynamicModel::validateData(
-            ['month' => $month, 'year' => $year, 'storeId' => $storeId],
+            ['month' => $month, 'year' => $year, 'storeId' => $storeId, 'matrix' => $matrix],
             [
+                ['matrix', 'each', 'rule' => ['string']],
                 [['month', 'year', 'storeId'], 'required'],
                 ['month', 'integer', 'min' => 1, 'max' => 12],
                 ['storeId', 'integer', 'min' => 1, 'max' => 100],
@@ -329,7 +331,7 @@ class BouquetController extends Controller
             $model->storeId  = $storeId;
         }
 
-               $result = StorePlanService::getBouquetSpiecesMonthGoalFromForecast($month, $year, $storeId);
+               $result = StorePlanService::getBouquetSpiecesMonthGoalFromForecast($month, $year, $storeId, $matrix);
 //var_dump($result); die();
         $stores = CityStore::find()
             ->select(['id', 'name'])
@@ -337,6 +339,11 @@ class BouquetController extends Controller
             ->asArray()
             ->all();
         $storesMap = ArrayHelper::map($stores, 'id', 'name');
+        $matrixGroups = ArrayHelper::map(
+            MatrixBouquetForecast::find()->select(['group'])->distinct()->asArray()->all(),
+            'group',
+            'group'
+        );
 
         return $this->render('month-goal-forecast', [
             'model'     => $model,   // передаём динамическую модель
@@ -344,6 +351,7 @@ class BouquetController extends Controller
             'storesMap' => $storesMap,
             'month'     => $month,
             'year'      => $year,
+            'matrixGroups'      => $matrixGroups,
         ]);
     }
     public function actionGetGuidBouquets()
@@ -379,8 +387,8 @@ class BouquetController extends Controller
 
                     $forecast = MatrixBouquetForecast::find()
                         ->where([
-                            'bouquet_name'  => $name,
-                            'bouquet_group' => $group,
+                            'name'  => $name,
+                            'group' => $group,
                             'year'          => $year,
                             'month'         => $month,
                         ])
@@ -403,15 +411,15 @@ class BouquetController extends Controller
                         }
                     } else {
                         $forecast = new MatrixBouquetForecast();
-                        $forecast->bouquet_name = $name;
-                        $forecast->bouquet_group = $group;
+                        $forecast->name = $name;
+                        $forecast->group = $group;
                         $forecast->year = $year;
                         $forecast->month = $month;
                         $forecast->created_at = date('Y-m-d H:i:s');
                         $forecast->updated_at = date('Y-m-d H:i:s');
 
                         $product = Products1c::find()->select(['id'])->where(['name' => $name])->one();
-                        $forecast->bouquet_id = $product ? $product->id : null;
+                        $forecast->guid = $product ? $product->id : null;
 
                         foreach ($newValues as $field => $value) {
                             $forecast->$field = $value;
index e730e3988b66d3da79f3f9bec26b8388c8d3cf34..0251e7f54781cf0177d508607384d414660b8002 100644 (file)
@@ -18,9 +18,9 @@ class m250514_143555_create_matrix_bouquet_forecast_table extends Migration
         if (!isset($tableSchema)) {
             $this->createTable(self::TABLE_NAME, [
                 'id' => $this->primaryKey(),
-                'bouquet_id' => $this->string()->comment('ИД букета'),
-                'bouquet_name' => $this->string()->comment('Наименование букета'),
-                'bouquet_group' => $this->string()->comment('Матрица букета'),
+                'guid' => $this->string()->comment('ИД букета'),
+                'name' => $this->string()->comment('Наименование букета'),
+                'group' => $this->string()->comment('Матрица букета'),
                 'year' => $this->integer()->comment('Год'),
                 'month' => $this->integer()->comment('Месяц'),
                 's_store' => $this->integer()->comment('Прогноз для оффлайн магазинов типа s'),
index 9ab692ed537c3d72ae67b93f0730126bc079dc9d..12669fafbb19e8cafd07563f7a13070fc64e318a 100644 (file)
@@ -8,9 +8,9 @@ use Yii;
  * This is the model class for table "matrix_bouquet_forecast".
  *
  * @property int $id
- * @property string|null $bouquet_id ИД букета
- * @property string|null $bouquet_name Наименование букета
- * @property string|null $bouquet_group Матрица букета
+ * @property string|null $guid ИД букета
+ * @property string|null $name Наименование букета
+ * @property string|null $group Матрица букета
  * @property int|null $year Год
  * @property int|null $month Месяц
  * @property int|null $s_store Прогноз для оффлайн магазинов типа s
@@ -40,11 +40,11 @@ class MatrixBouquetForecast extends \yii\db\ActiveRecord
     public function rules()
     {
         return [
-            [['bouquet_id', 'bouquet_name', 'bouquet_group', 'year', 'month', 's_store', 'm_store', 'l_store', 'xl_store', 'marketplace', 'internet', 'created_at', 'updated_at'], 'default', 'value' => null],
+            [['guid', 'name', 'group', 'year', 'month', 's_store', 'm_store', 'l_store', 'xl_store', 'marketplace', 'internet', 'created_at', 'updated_at'], 'default', 'value' => null],
             [['year', 'month', 's_store', 'm_store', 'l_store', 'xl_store', 'marketplace', 'internet'], 'default', 'value' => null],
             [['year', 'month', 's_store', 'm_store', 'l_store', 'xl_store', 'marketplace', 'internet'], 'integer'],
             [['created_at', 'updated_at'], 'safe'],
-            [['bouquet_id', 'bouquet_name', 'bouquet_group'], 'string', 'max' => 255],
+            [['guid', 'name', 'group'], 'string', 'max' => 255],
         ];
     }
 
@@ -55,9 +55,9 @@ class MatrixBouquetForecast extends \yii\db\ActiveRecord
     {
         return [
             'id' => 'ID',
-            'bouquet_id' => 'Bouquet ID',
-            'bouquet_name' => 'Bouquet Name',
-            'bouquet_group' => 'Bouquet Group',
+            'guid' => 'Guid',
+            'name' => 'Name',
+            'group' => 'Group',
             'year' => 'Year',
             'month' => 'Month',
             's_store' => 'S Store',
index a5664825b88f774d18e2187395efa27dcff41a97..4dcb214b09e755bee7abcb0880d97d13249bac97 100755 (executable)
@@ -911,10 +911,10 @@ class StorePlanService
     }
 
 
-    public static function getBouquetSpiecesMonthGoalFromForecast($month, $year, $storeId = null)
+    public static function getBouquetSpiecesMonthGoalFromForecast($month, $year, $storeId = null, $matrixGroups = [])
     {
         $stores = [];
-
+        $forecasts = [];
         if (!empty($storeId)) {
             $stores[] = $storeId;
         } else {
@@ -927,120 +927,138 @@ class StorePlanService
                 'id'
             );
         }
-       // var_dump($stores); die();
-        $storesParams = CityStoreParams::find()
-                ->select(['store_id', 'address_region', 'store_type'])
-                ->where(['store_id' => $stores])
-                ->andWhere(['not', ['address_region' => '']])
-                ->asArray()
-                ->indexBy('store_id')
-                ->all();
+        $types = [
+            's_store' => 'offline',
+            'm_store' => 'offline',
+            'l_store' => 'offline',
+            'xl_store' => 'offline',
+            'marketplace' => 'marketplace',
+            'internet' => 'online'
+        ];
+
+        $storeSizeTypes = [
+            1 => 's_store',
+            2 => 'm_store',
+            3 => 'l_store',
+            4 => 'xl_store',
 
-        $forecasts = MatrixBouquetForecast::find()
-            ->where(['year' => $year, 'month' => $month])
-            ->andWhere(['not', ['bouquet_id' => null]])
+        ];
+        // var_dump($stores); die();
+        $storesParams = CityStoreParams::find()
+            ->select(['store_id', 'address_region', 'store_type'])
+            ->where(['store_id' => $stores])
+            ->andWhere(['not', ['address_region' => '']])
             ->asArray()
+            ->indexBy('store_id')
             ->all();
-       // var_dump($forecasts); die();
+
         $resultData = [];
         $debugData = [];
+        if (!empty($matrixGroups)) {
+            foreach ($matrixGroups as $matrixGroup) {
+                $forecasts = MatrixBouquetForecast::find()
+                    ->where(['year' => $year, 'month' => $month])
+                    ->andWhere(['not', ['guid' => null]])
+                    ->andWhere(['group' => $matrixGroup])
+                    ->asArray()
+                    ->all();
+                foreach ($forecasts as $forecast) {
+                    $products = [];
+
+                    $product = Products1c::find()
+                        ->select(['components'])
+                        ->where(['id' => $forecast['guid']])
+                        ->asArray()
+                        ->one();
+
+                    if ($product && !empty($product['components'])) {
+                        $components = json_decode($product['components'], true);
+                        if (is_array($components)) {
+                            foreach ($components as $productId => $count) {
+                                $products[] = [
+                                    'product_guid' => $productId,
+                                    'count' => (float)$count,
+                                ];
+                            }
+                        }
+                    }
 
-        foreach ($forecasts as $forecast) {
-            $products = [];
+                    $productGuids = array_filter(array_column($products, 'product_guid'));
 
-            $product = Products1c::find()
-                ->select(['components'])
-                ->where(['id' => $forecast['bouquet_id']])
-                ->asArray()
-                ->one();
-
-            if ($product && !empty($product['components'])) {
-                $components = json_decode($product['components'], true);
-                if (is_array($components)) {
-                    foreach ($components as $productId => $count) {
-                        $products[] = [
-                            'product_guid' => $productId,
-                            'count' => (float)$count,
-                        ];
-                    }
-                }
-            }
 
-            $productGuids = array_filter(array_column($products, 'product_guid'));
 
-            $types = [
-                's_store' => 'offline',
-                'm_store' => 'offline',
-                'l_store' => 'offline',
-                'xl_store' => 'offline',
-                'marketplace' => 'marketplace',
-                'internet' => 'online'
-            ];
 
-            $storeSizeTypes = [
-                 1 => 's_store',
-                2 => 'm_store',
-                3 => 'l_store',
-                4 => 'xl_store',
 
-            ];
+                        foreach ($storesParams as $storeId => $params) {
+                            // var_dump($storesParams);die();
+                            foreach ($types as $field => $typeSales) {
 
-            foreach ($types as $field => $typeSales) {
-                
-                $typeSalesValue = (int)$forecast[$field];
-                if ($typeSalesValue <= 0) {
-                    continue;
-                }
+                                $typeSalesValue = (int)$forecast[$field];
+                                if ($typeSalesValue <= 0) {
+                                    continue;
+                                }
+                            }
+                            $regionId = $params['address_region'];
+                            if (!$regionId) {
+                                if (CityStore::find()->where(['id' => $storeId])->one()->city_id == 1342) {
+                                    $regionId = 52;
+                                } elseif (CityStore::find()->where(['id' => $storeId])->one()->city_id == 1) {
+                                    $regionId = 77;
+                                } else {
+                                    $regionId = 52;
+                                }
+                            }
 
-                foreach ($storesParams as $storeId => $params) {
-                    $regionId = $params['region_id'];
-                    if (!$regionId) {
-                        if (CityStore::find()->where(['id' => $storeId])->one()->city_id == 1342) {
-                            $regionId = 52;
-                        } elseif (CityStore::find()->where(['id' => $storeId])->one()->city_id == 1) {
-                            $regionId = 77;
-                        } else {
-                            $regionId = null;
+                            $pricesData = ArrayHelper::map(
+                                PricesDynamic::find()
+                                    ->where(['product_id' => $productGuids])
+                                    ->andWhere(['active' => 1])
+                                    ->andWhere(['region_id' => $regionId])
+                                    ->select(['price', 'product_id'])
+                                    ->asArray()
+                                    ->all(),
+                                'product_id',
+                                'price'
+                            );
+
+                            foreach ($products as $product) {
+                                $productModel = Products1cNomenclature::findOne($product['product_guid']);
+                                $species = $productModel?->species ?? 'Неизвестно';
+                                $basePrice = $pricesData[$product['product_guid']] ?? 0;
+                                $rawCalculation = $basePrice * $product['count'] * $typeSalesValue;
+                                $productCost = round($rawCalculation * 1.15, 2);
+
+                                if (!isset($resultData[$storeId][$species][$typeSales])) {
+                                    $resultData[$storeId][$species][$typeSales] = 0;
+                                }
+                                $resultData[$storeId][$species][$typeSales] += $productCost;
+
+                                $debugData[$storeId][$species][$typeSales][] = [
+                                    'product_guid' => $product['product_guid'],
+                                    'price' => $basePrice,
+                                    'count' => $product['count'],
+                                    'forecast' => $typeSalesValue,
+                                    'guid' => $forecast['guid'],
+                                    'raw_calculation' => $rawCalculation,
+                                    'rounded' => $productCost,
+                                ];
+                            }
                         }
-                    }
 
-                    $pricesData = ArrayHelper::map(
-                        PricesDynamic::find()
-                            ->where(['product_id' => $productGuids])
-                            ->andWhere(['active' => 1])
-                            ->andWhere(['or', ['region_id' => $regionId], ['region_id' => null]])
-                            ->select(['price', 'product_id'])
-                            ->asArray()
-                            ->all(),
-                        'product_id',
-                        'price'
-                    );
-
-                    foreach ($products as $product) {
-                        $productModel = Products1cNomenclature::findOne($product['product_guid']);
-                        $species = $productModel?->species ?? 'Неизвестно';
-                        $basePrice = $pricesData[$product['product_guid']] ?? 0;
-                        $rawCalculation = $basePrice * $product['count'] * $typeSalesValue;
-                        $productCost = round($rawCalculation * 1.15, 2);
-
-                        if (!isset($resultData[$storeId][$species][$typeSales])) {
-                            $resultData[$storeId][$species][$typeSales] = 0;
-                        }
-                        $resultData[$storeId][$species][$typeSales] += $productCost;
-
-                        $debugData[$storeId][$species][$typeSales][] = [
-                            'product_guid' => $product['product_guid'],
-                            'price' => $basePrice,
-                            'count' => $product['count'],
-                            'forecast' => $typeSalesValue,
-                            'bouquet_id' => $forecast['bouquet_id'],
-                            'raw_calculation' => $rawCalculation,
-                            'rounded' => $productCost,
-                        ];
-                    }
                 }
             }
+        } else {
+           return [
+                'detail' => [],
+                'final' => [],
+                'debug' => []
+            ];
         }
+        // var_dump($forecasts); die();
+
+       // var_dump( $forecasts); die();
+
+
 
         $finalResult = [];
         foreach ($resultData as $storeId => $speciesData) {
@@ -1051,8 +1069,8 @@ class StorePlanService
 
         return [
             'detail' => $resultData,
-            'final'  => $finalResult,
-            'debug'  => $debugData
+            'final' => $finalResult,
+            'debug' => $debugData
         ];
     }
 
index c5371230a8d2466813bb432478fc0194ed9ecdc9..e63d9a14d3f1ca493957b70fb726342d59b80c64 100644 (file)
@@ -25,13 +25,13 @@ $this->title = 'Импорт прогноза по букетам';
         'dataProvider' => $dataProvider,
         'columns' => [
             'id',
-            'bouquet_id',
+            'guid',
             [
-                'attribute' => 'bouquet_group',
+                'attribute' => 'group',
                 'label' => 'Группа букета',
             ],
             [
-                'attribute' => 'bouquet_name',
+                'attribute' => 'name',
                 'label' => 'Название букета',
             ],
             'year',
index 227cf122901e3bbfc784b8844dbbf2627a54e5a1..3026eb771e962584f77ad65b6180b21bed4101b0 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 use kartik\grid\GridView;
+use kartik\select2\Select2;
 use yii\helpers\Html;
 use yii\helpers\Url;
 use yii\widgets\ActiveForm;
@@ -12,6 +13,7 @@ use yii\data\ArrayDataProvider;
 /* @var $storesMap array */
 /* @var $month int */
 /* @var $year int */
+/* @var $matrixGroups array */
 
 $saleTypesLabels = [
     1 => 'Оффлайн',
@@ -34,6 +36,17 @@ $saleTypesLabels = [
         <?= $form->field($model, 'year')->input('number')->label('Год') ?>
         <?= $form->field($model, 'storeId')->dropDownList($storesMap)->label('Магазин') ?>
 
+        <?= $form->field($model, 'matrix')->widget(\kartik\select2\Select2::class, [
+            'data' => $matrixGroups,
+            'language' => 'ru',
+            'options' => [
+                'placeholder' => 'Выберите группы матриц',
+                'multiple' => true,
+            ],
+            'pluginOptions' => [
+                'allowClear' => true,
+            ],
+        ])->label('Группы матриц') ?>
         <div class="form-group">
             <?= Html::submitButton('Показать', ['class' => 'btn btn-primary']) ?>
         </div>
@@ -120,9 +133,9 @@ $saleTypesLabels = [
                                      " (" . $model['product_guid'] . ")";
                             },
                             'label' => 'Product GUID'],
-                        ['attribute' => 'bouquet_id',
+                        ['attribute' => 'guid',
                             'value' => function ($model, $key, $index, $widget) {
-                                return \yii_app\records\MatrixBouquetForecast::find()->where(['bouquet_id' => $model['bouquet_id']])->one()->bouquet_name;
+                                return \yii_app\records\MatrixBouquetForecast::find()->where(['guid' => $model['guid']])->one()->name;
                             },
                             'label' => 'Букет'],
                         ['attribute' => 'price',            'label' => 'Цена'],
@@ -214,11 +227,11 @@ $saleTypesLabels = [
                 }
             ],
             [
-                'attribute' => 'bouquet_id',
+                'attribute' => 'guid',
                 'label'     => 'Букет',
                 'value' => function ($model, $key, $index, $widget) {
-                    $bouquet = \yii_app\records\MatrixBouquetForecast::find()->where(['bouquet_id' => $model['bouquet_id']])->one();
-                    return $bouquet ? $bouquet->bouquet_name : $model['bouquet_id'];
+                    $bouquet = \yii_app\records\MatrixBouquetForecast::find()->where(['guid' => $model['guid']])->one();
+                    return $bouquet ? $bouquet->name : $model['guid'];
                 }
             ],
             ['attribute' => 'price',           'label' => 'Цена'],