From: fomichev Date: Sun, 6 Apr 2025 20:16:13 +0000 (+0300) Subject: Анализ товаров без истории X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=df4141e2550b074004377fde5cad198dbb678878;p=erp24_rep%2Fyii-erp24%2F.git Анализ товаров без истории --- diff --git a/erp24/controllers/CategoryPlanController.php b/erp24/controllers/CategoryPlanController.php index 33a3110e..3e60567d 100644 --- a/erp24/controllers/CategoryPlanController.php +++ b/erp24/controllers/CategoryPlanController.php @@ -349,12 +349,19 @@ class CategoryPlanController extends Controller { $subcategory, $species ); + $weightedResults = StorePlanService::calculateWeightedSalesForProductsWithoutHistory( + $storeId, + $selectedMonth, + $result['without_history'] + ); + } } } return $this->render('show-history-data', [ 'result' => $result, + 'weighted' => $weightedResults, 'model' => $model, 'storeList' => $storeList, 'monthsList' => $monthsList, diff --git a/erp24/services/StorePlanService.php b/erp24/services/StorePlanService.php index 2b7f1477..58c56ce4 100755 --- a/erp24/services/StorePlanService.php +++ b/erp24/services/StorePlanService.php @@ -6,6 +6,7 @@ use DateTime; use yii\db\Expression; use yii\helpers\ArrayHelper; use yii_app\records\Motivation; +use yii_app\records\Products1cAdditionalCharacteristics; use yii_app\records\Sales; use yii_app\records\SalesProducts; use yii_app\records\StorePlan; @@ -316,5 +317,127 @@ class StorePlanService ]; } + + /** + * Метод вычисляет взвешенное значение продаж для товаров без истории. + * + * @param int $storeId Идентификатор магазина. + * @param string $selectedMonth Выбранный месяц в формате "mm" (целевой месяц). + * @param array $productsWithoutHistory Массив товаров без истории, где каждый элемент имеет вид: + * [ + * 'guid' => , + * 'weekly_sales' => [ 'YYYY-mm' => [ ... ], ... ] + * ] + * @return array Возвращает массив, где ключ – GUID товара, а значение – рассчитанное взвешенное значение продаж. + */ + public static function calculateWeightedSalesForProductsWithoutHistory($storeId, $selectedMonth, $productsWithoutHistory) + { + + $year = date('Y'); + $targetDate = strtotime("$year-$selectedMonth-01"); + + $months = []; + for ($i = 1; $i <= 3; $i++) { + $monthTimestamp = strtotime("-{$i} month", $targetDate); + $m = date('m', $monthTimestamp); + $y = date('Y', $monthTimestamp); + $months[] = ['year' => $y, 'month' => $m]; + } + + $weightedResults = []; + + foreach ($productsWithoutHistory as $product) { + $guid = $product['guid']; + //var_dump( $guid); die(); + $myChars = Products1cAdditionalCharacteristics::find() + ->where(['product_id' => $guid]) + ->asArray() + ->all(); + + $mySet = []; + foreach ($myChars as $char) { + $mySet[$char['property_id']] = $char['value']; + } + ksort($mySet); + // var_dump($mySet); die(); + $countChars = count($mySet); + // var_dump($countChars); die(); + if ($countChars == 0) { + $weightedResults[$guid] = 0; + continue; + } + + $conditions = []; + foreach ($mySet as $propId => $val) { + $conditions[] = [$propId, $val]; + } + $query = Products1cAdditionalCharacteristics::find() + ->select('product_id') + ->where(new \yii\db\Expression('(property_id, value) IN (' . implode(', ', array_map(function($pair) { + return "('" . implode("','", $pair) . "')"; + }, $conditions)) . ')')) + ->groupBy('product_id') + ->having('COUNT(*) = :cnt', [':cnt' => $countChars]); + + $similarProductIds = $query->column(); + // var_dump($similarProductIds); die(); + if (empty($similarProductIds)) { + $weightedResults[$guid] = 0; + continue; + } + + $medianSales = []; + $salesValuesForEachMonth = []; + foreach ($months as $monthInfo) { + $startDate = sprintf('%04d-%02d-01', $monthInfo['year'], $monthInfo['month']); + $endDate = sprintf('%04d-%02d-%02d', + $monthInfo['year'], + $monthInfo['month'], + cal_days_in_month(CAL_GREGORIAN, $monthInfo['month'], $monthInfo['year'])); + + $salesValues = []; + + foreach ($similarProductIds as $simProdId) { + $sales = Sales::find()->alias('s') + ->innerJoin('sales_products sp', 's.id = sp.check_id') + ->innerJoin('products_1c_nomenclature p1c', 'p1c.id = sp.product_id') + ->where(['p1c.id' => $simProdId]) + ->andWhere(['s.store_id' => $storeId]) + ->andWhere(['between', 's.date', $startDate . ' 00:00:00', $endDate . ' 23:59:59']) + // Условие для чеков: order_id равен '' или '0' + ->andWhere(['order_id' => ['', '0']]) + ->count(); + $salesValues[] = (int)$sales; + } + $salesValuesForEachMonth[] = $salesValues; + $nonZeroSales = array_filter($salesValues, function($val) { + return $val > 0; + }); + sort($nonZeroSales, SORT_NUMERIC); + $n = count($nonZeroSales); + if ($n === 0) { + $median = 0; + } elseif ($n % 2 == 1) { + $median = $nonZeroSales[floor($n / 2)]; + } else { + $median = ($nonZeroSales[$n / 2 - 1] + $nonZeroSales[$n / 2]) / 2; + } + $medianSales[] = $median; + } + + $weights = [3, 2, 1]; + $weightedValue = 0; + for ($i = 0; $i < count($medianSales); $i++) { + $weightedValue += $medianSales[$i] * $weights[$i]; + } + $weightedResults[$guid] = [ + 'weightedValue' => $weightedValue, + 'medianSales' => $medianSales, + 'salesValues' => $salesValuesForEachMonth, + ]; + } + return $weightedResults; + } + } diff --git a/erp24/views/category-plan/show-history-data.php b/erp24/views/category-plan/show-history-data.php index 4c29a4ef..3db4f027 100644 --- a/erp24/views/category-plan/show-history-data.php +++ b/erp24/views/category-plan/show-history-data.php @@ -4,12 +4,14 @@ use yii\helpers\ArrayHelper; use yii\widgets\ActiveForm; use yii\base\DynamicModel; use yii_app\records\CityStore; +use yii_app\records\Products1c; use yii_app\records\Products1cNomenclature; /* @var $this yii\web\View */ /* @var $result array|null */ +/* @var $weighted array|null */ /* @var $model DynamicModel */ /* @var $storeList array */ /* @var $monthsList array */ @@ -130,20 +132,46 @@ JS; - + + + + - + + + + @@ -151,6 +179,5 @@ JS;

Нет товаров без истории продаж.

-
GUID продуктаНаименование продукта Недельные продажиСредневзвешенные продажиОтладочные данныеВычесленная стоимость
(средневзвешенное кол-во Х цена)
+ where(['id' => $product['guid']])->one(); + echo ($productModel !== null) ? Html::encode($productModel->name) : Html::encode($product['guid']); + ?> + $weekData): ?> :
+ + + + Медианы продаж:
+ Продажи за месяц:
+ $salesArray): ?> + Месяц :
+ + +
+ where(['product_id' => $product['guid']]) + ->andWhere(['active' => 1])->one()->price) * + $weighted[$product['guid']]['weightedValue'] : 0 ?> +