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;
];
}
+
+ /**
+ * Метод вычисляет взвешенное значение продаж для товаров без истории.
+ *
+ * @param int $storeId Идентификатор магазина.
+ * @param string $selectedMonth Выбранный месяц в формате "mm" (целевой месяц).
+ * @param array $productsWithoutHistory Массив товаров без истории, где каждый элемент имеет вид:
+ * [
+ * 'guid' => <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;
+ }
+
}
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 */
<table class="table table-bordered">
<thead>
<tr>
- <th>GUID продукта</th>
+ <th>Наименование продукта</th>
<th>Недельные продажи</th>
+ <th>Средневзвешенные продажи</th>
+ <th>Отладочные данные</th>
+ <th>Вычесленная стоимость<br> (средневзвешенное кол-во Х цена)</th>
</tr>
</thead>
<tbody>
<?php foreach ($result['without_history'] as $product): ?>
<tr>
- <td><?= Html::encode($product['guid']) ?></td>
+ <td>
+ <?php
+ $productModel = Products1c::find()->where(['id' => $product['guid']])->one();
+ echo ($productModel !== null) ? Html::encode($productModel->name) : Html::encode($product['guid']);
+ ?>
+ </td>
<td>
<?php foreach ($product['weekly_sales'] as $month => $weekData): ?>
<strong><?= Html::encode($month) ?>:</strong>
<?= implode(', ', $weekData) ?><br>
<?php endforeach; ?>
</td>
+ <td>
+ <?= isset($weighted[$product['guid']]) ? $weighted[$product['guid']]['weightedValue'] : 0 ?>
+ </td>
+ <td>
+ <?php if(isset($weighted[$product['guid']])): ?>
+ <strong>Медианы продаж:</strong> <?= implode(', ', $weighted[$product['guid']]['medianSales']) ?><br>
+ <strong>Продажи за месяц:</strong><br>
+ <?php foreach ($weighted[$product['guid']]['salesValues'] as $monthIndex => $salesArray): ?>
+ Месяц <?= $monthIndex+1 ?>: <?= implode(', ', $salesArray) ?><br>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ </td>
+ <td>
+ <?= isset($weighted[$product['guid']]) ? (\yii_app\records\PricesDynamic::find()
+ ->where(['product_id' => $product['guid']])
+ ->andWhere(['active' => 1])->one()->price) *
+ $weighted[$product['guid']]['weightedValue'] : 0 ?>
+ </td>
</tr>
<?php endforeach; ?>
</tbody>
<?php else: ?>
<p>Нет товаров без истории продаж.</p>
<?php endif; ?>
-
<?php endif; ?>
</div>