]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Коректировки по ценам товаров без истории - расчет по неделям
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 21 May 2025 13:45:35 +0000 (16:45 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 21 May 2025 13:45:35 +0000 (16:45 +0300)
erp24/services/StorePlanService.php

index 0911a597a224a47f2e2bb3828b2d8b8f06b4a1e2..d660a6d31d4ecccc5a807b44655ce310aa76a831 100755 (executable)
@@ -536,6 +536,20 @@ class StorePlanService
         $tYear  = (int)$target->format('Y');
         $tMonth = (int)$target->format('m');
 
+        $region = CityStoreParams::find()
+            ->where(['store_id' => $storeId])
+            ->one()->address_region;
+
+        if (!$region) {
+            // определяем регион по городу
+            $cityId = CityStore::find()->select('city_id')->where(['id' => $storeId])->scalar();
+            if ($cityId == 1) {
+                $region = BouquetComposition::REGION_MSK;
+            } else {
+                $region = BouquetComposition::REGION_NN;
+            }
+        }
+
         $monthStart = sprintf('%04d-%02d-01', $tYear, $tMonth);
         $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $tMonth, $tYear);
         $monthEnd   = sprintf('%04d-%02d-%02d', $tYear, $tMonth, $daysInMonth);
@@ -543,6 +557,7 @@ class StorePlanService
         $priceRecords = PricesDynamic::find()
             ->where(['product_id' => $productId])
             ->andWhere(['<=', 'date_from', $monthEnd])
+            ->andWhere(['region_id' => $region])
             ->andWhere([
                 'or',
                 ['>=', 'date_to',   $monthStart],
@@ -550,18 +565,6 @@ class StorePlanService
             ])
             ->all();
 
-        // определяем регион по городу
-        $cityId = CityStore::find()->select('city_id')->where(['id' => $storeId])->scalar();
-        if ($cityId == 1342) {
-            $region = BouquetComposition::REGION_NN;
-        } elseif ($cityId == 1) {
-            $region = BouquetComposition::REGION_MSK;
-        } else {
-            $region = null;
-        }
-
-        // ->andWhere(['or', ['region_id' => $region], ['region_id' => null]])
-
         if (empty($priceRecords)) {
             return 0.0;
         }
@@ -578,6 +581,74 @@ class StorePlanService
         return $count > 0 ? ($total / $count) : 0.0;
     }
 
+    public static function getPriceForProductAtOffsetMonthWeekly(
+        string $productId,
+        int    $year,
+        int    $month,
+        int    $storeId,
+        int    $offset = 2
+    ): float {
+        $date = new \DateTimeImmutable(sprintf('%04d-%02d-01', $year, $month));
+        $target = $date->modify(sprintf('-%d months', $offset));
+        $tYear  = (int)$target->format('Y');
+        $tMonth = (int)$target->format('m');
+
+        $region = CityStoreParams::find()
+            ->where(['store_id' => $storeId])
+            ->select('address_region')
+            ->scalar();
+        if (!$region) {
+            $cityId = CityStore::find()->where(['id' => $storeId])->select('city_id')->scalar();
+            $region = $cityId === 1
+                ? BouquetComposition::REGION_MSK
+                : BouquetComposition::REGION_NN;
+        }
+
+        $monthStart = new \DateTimeImmutable(sprintf('%04d-%02d-01', $tYear, $tMonth));
+        $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $tMonth, $tYear);
+        $monthEnd   = $monthStart->modify(sprintf('+%d days', $daysInMonth - 1));
+
+        $interval = new \DateInterval('P1W');
+        $period = new \DatePeriod(
+            $monthStart,
+            $interval,
+            $monthEnd->modify('+1 day')
+        );
+
+        $weeklyAverages = [];
+
+        foreach ($period as $weekStart) {
+            $potentialEnd = $weekStart->modify('+6 days');
+            $weekEnd = $potentialEnd > $monthEnd ? $monthEnd : $potentialEnd;
+
+            $priceRecords = PricesDynamic::find()
+                ->where(['product_id' => $productId, 'region_id' => $region])
+                ->andWhere(['<=', 'date_from', $weekEnd->format('Y-m-d')])
+                ->andWhere([
+                    'or',
+                    ['>=', 'date_to',   $weekStart->format('Y-m-d')],
+                    ['date_to' => '2100-01-01 03:00:00+03']
+                ])
+                ->all();
+
+            $sum = 0; $cnt = 0;
+            foreach ($priceRecords as $rec) {
+                if (isset($rec->price)) {
+                    $sum += $rec->price;
+                    $cnt++;
+                }
+            }
+            $weeklyAverages[] = $cnt > 0 ? ($sum / $cnt) : 0.0;
+        }
+
+        if (empty($weeklyAverages)) {
+            return 0.0;
+        }
+
+        // Среднее арифметическое всех недельных средних
+        $total = array_sum($weeklyAverages);
+        return $total / count($weeklyAverages);
+    }
 
     /**
      * Рассчитывает итоговые стоимости для товаров без истории, группируя суммы по
@@ -605,20 +676,20 @@ class StorePlanService
         int   $storeId,
         int   $selectedMonth,
         int   $selectedYear,
-        array $weightedProductsWithoutHistory
+        array $productsWithoutHistory
     ): array
     {
 
         $accumulator = [];
 
-        foreach ($weightedProductsWithoutHistory as $guid => $info) {
+        foreach ($productsWithoutHistory as $guid => $info) {
             $quantity = (float)$info;
             if ($quantity <= 0) {
                 continue;
             }
 
             // цена за два месяца назад
-            $price = self::getPriceForProductAtOffsetMonth(
+            $price = self::getPriceForProductAtOffsetMonthWeekly(
                 $guid,
                 $selectedYear,
                 $selectedMonth,