$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],
$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'])
->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, // передаём динамическую модель
'storesMap' => $storesMap,
'month' => $month,
'year' => $year,
+ 'matrixGroups' => $matrixGroups,
]);
}
public function actionGetGuidBouquets()
$forecast = MatrixBouquetForecast::find()
->where([
- 'bouquet_name' => $name,
- 'bouquet_group' => $group,
+ 'name' => $name,
+ 'group' => $group,
'year' => $year,
'month' => $month,
])
}
} 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;
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'),
* 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
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],
];
}
{
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',
}
- 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 {
'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) {
return [
'detail' => $resultData,
- 'final' => $finalResult,
- 'debug' => $debugData
+ 'final' => $finalResult,
+ 'debug' => $debugData
];
}
'dataProvider' => $dataProvider,
'columns' => [
'id',
- 'bouquet_id',
+ 'guid',
[
- 'attribute' => 'bouquet_group',
+ 'attribute' => 'group',
'label' => 'Группа букета',
],
[
- 'attribute' => 'bouquet_name',
+ 'attribute' => 'name',
'label' => 'Название букета',
],
'year',
<?php
use kartik\grid\GridView;
+use kartik\select2\Select2;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
/* @var $storesMap array */
/* @var $month int */
/* @var $year int */
+/* @var $matrixGroups array */
$saleTypesLabels = [
1 => 'Оффлайн',
<?= $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>
" (" . $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' => 'Цена'],
}
],
[
- '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' => 'Цена'],