]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Вывод расчетов
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 15 Apr 2025 15:03:16 +0000 (18:03 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 15 Apr 2025 15:03:16 +0000 (18:03 +0300)
erp24/controllers/BouquetController.php
erp24/records/BouquetComposition.php
erp24/services/StorePlanService.php
erp24/views/bouquet/month-goal.php [new file with mode: 0644]

index 2d23296cc0f61b419bd4eb7aa84b037a0e5693a0..e3e0f85ae1fd2d5b9875e6597f30c002ca6a44ab 100644 (file)
@@ -13,12 +13,16 @@ use yii\web\NotFoundHttpException;
 use yii\web\Response;
 use yii_app\helpers\DataHelper;
 use yii_app\records\{BouquetComposition,
+    BouquetCompositionPrice,
     BouquetCompositionProducts,
     BouquetForecast,
     CityStore,
+    CityStoreParams,
     Files,
     MatrixType,
+    PricesDynamic,
     Products1cNomenclature,
+    SelfCostProduct,
     StoreType,
     WriteOffsErp};
 use yii_app\services\StorePlanService;
@@ -249,19 +253,27 @@ class BouquetController extends Controller
         return $data;
     }
 
-    public function actionMonthGoal()
+    public function actionMonthGoal($month, $year)
     {
-        $matrixTypesIds = StorePlanService::getActiveMatrixTypes();
-       // var_dump($matrixTypesIds);die();
-        $bouquets = [];
-        if ($matrixTypesIds) {
-            foreach ($matrixTypesIds as $matrixTypeId) {
-                $bouquets[$matrixTypeId] = StorePlanService::getBouqetsByDate(5, 2025, $matrixTypeId);
-            }
-        }
 
+        $result = StorePlanService::getBouquetSpiecesMonthGoal($month, $year);
+
+        $month = $month ?? 5;
+        $year = $year ?? 2025;
+        $stores = CityStore::find()
+            ->select(['id', 'name'])
+            ->where(['visible' => CityStore::IS_VISIBLE])
+            ->asArray()
+            ->all();
 
-        var_dump($bouquets);die();
+        $storesMap = ArrayHelper::map($stores, 'id', 'name');
 
+
+        return $this->render('month-goal', [
+            'result'    => $result,
+            'storesMap' => $storesMap,
+            'month'     => $month,
+            'year'      => $year,
+        ]);
     }
 }
index 9a70d7541d097634d053ff771646d42bdb9eaef2..873f9781f263279ea2d77891ccfc484b25f71abc 100644 (file)
@@ -457,6 +457,7 @@ class BouquetComposition extends ActiveRecord
                 $costModel->bouquet_id = $this->id;
                 $costModel->region_id = $region_id;
             }
+            // TODO  не понятно как задается региональность цены - точнее как она от региона зависит
             $costModel->selfcost = $this->getSelfCost($data);
             $costModel->selfcost_markup = 30;
             $costModel->selfcost_markup_price = 0.3 * $costModel->selfcost;
index 6fcd365b2f9ba3f2135a7a1141cddd2a8c28b863..98bab0ec4ba62371fc268479f6aa8291c994761b 100755 (executable)
@@ -7,13 +7,19 @@ use yii\db\Expression;
 use yii\helpers\ArrayHelper;
 use yii_app\records\BouquetComposition;
 use yii_app\records\BouquetCompositionMatrixTypeHistory;
+use yii_app\records\BouquetCompositionPrice;
+use yii_app\records\BouquetCompositionProducts;
+use yii_app\records\BouquetForecast;
 use yii_app\records\CityStore;
+use yii_app\records\CityStoreParams;
 use yii_app\records\Motivation;
 use yii_app\records\PricesDynamic;
 use yii_app\records\Products1cAdditionalCharacteristics;
+use yii_app\records\Products1cNomenclature;
 use yii_app\records\Sales;
 use yii_app\records\SalesProducts;
 use yii_app\records\StorePlan;
+use yii_app\records\StoreType;
 use yii_app\records\WriteOffsErp;
 
 class StorePlanService
@@ -763,15 +769,25 @@ class StorePlanService
 
     public static function getBouqetsByDate($month, $year, $matrix_type = null) {
         $query = BouquetComposition::find()
+            ->select([
+                'bouquet_composition.*',
+                'bf.year AS forecast_year',
+                'bf.month AS forecast_month',
+
+
+            ])
             ->orderBy(['id' => SORT_DESC])
-            ->groupBy('bouquet_composition.id')
+            ->groupBy(['bouquet_composition.id', 'bf.year',
+                'bf.month'])
             ->andWhere(['status' => [
                 WriteOffsErp::STATUS_CREATED_1С,
 
             ]])
-            ->joinWith('bouquetForecast as bf')
-            ->andWhere(['bf.year' => $year])
-            ->andWhere(['bf.month' => $month]);
+            ->innerJoinWith(['bouquetForecast bf' => function($query) use ($year, $month) {
+                $query->andWhere(['bf.year' => $year])
+                    ->andWhere(['bf.month' => $month])
+                    ->andWhere(['not', ['bf.type_sales_value' => null]]);
+            }]);
 
         if ($matrix_type) {
             $query->leftJoin(
@@ -782,9 +798,116 @@ class StorePlanService
                 'mth.is_active' => true
             ]);
         }
+
         return $query->asArray()->all();
+
     }
 
+    public static function getBouquetSpiecesMonthGoal($month, $year) {
+        $stores = ArrayHelper::map(CityStore::find()->select(['id'])->where(['visible' => CityStore::IS_VISIBLE])->asArray()->all(), 'id', 'id');
+        $storesParams = ArrayHelper::map(CityStoreParams::find()
+            ->select(['store_id', 'address_region'])
+            ->where(['store_id' => array_keys($stores)])
+            ->andWhere(['not', ['address_region' => '']])
+            ->asArray()
+            ->indexBy('store_id')
+            ->all(), 'store_id', 'address_region');
+
+        $matrixTypesIds = StorePlanService::getActiveMatrixTypes();
+
+        $storesForecasts = [];
+        // получаем букеты из матрицы
+        if ($matrixTypesIds) {
+            foreach ($matrixTypesIds as $matrixTypeId) {
+                $bouquetsArray = StorePlanService::getBouqetsByDate($month, $year, $matrixTypeId);
+                $forecasts = ArrayHelper::getColumn($bouquetsArray , 'bouquetForecast');
+
+                foreach ($forecasts as $forecastArray) {
+                    if (is_array($forecastArray)) {
+                        foreach ($forecastArray as $fc) {
+                            $bouquetPrice = 0;
+                            if(isset($storesParams[$fc["type_sales_id"]])){
+                                $bouquetPrice = BouquetCompositionPrice::find()
+                                    ->where(['bouquet_id' => $fc['bouquet_id']])
+                                    ->andWhere(['region_id' => $storesParams[$fc["type_sales_id"]]])->one()->price;
+                            }
+
+                            $storesForecasts[] = array_merge($fc, ['matrixTypeId' => $matrixTypeId], ['price' => $bouquetPrice] );
+
+                        }
+                    }
+                }
+            }
+        }
+        $resultArr = [];
+        foreach ($storesForecasts as $storeForecast) {
+            $products = ArrayHelper::toArray(BouquetCompositionProducts::getCompositionProducts($storeForecast['bouquet_id']));
+            $productGuids = array_filter(array_column($products, 'product_guid'));
+            $pricesData = ArrayHelper::map(PricesDynamic::find()
+                ->where(['product_id' => $productGuids])
+                ->andWhere(['active' => 1])
+                ->andWhere(['region_id' => $storesParams[$fc["type_sales_id"]]])
+                ->select(['price', 'product_id'])->asArray()->all(), 'product_id', 'price') ;
+            // var_dump($products); die();
+            foreach ($products as $product) {
+                $species = Products1cNomenclature::find()->where(['id' => $product['product_guid']])->one()->species;
+                $productCost = round($pricesData[$product['product_guid']] * $product['count'] * 1.15, 2);
+                if (!isset($resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]])) {
+                    $resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]] = 0;
+                }
+                $resultArr[$storeForecast["type_sales_id"]][$species][$storeForecast["type_sales"]] += $productCost;
+
+            }
+
+        }
+        $finalResult = [];
+        foreach ($resultArr as $typeSalesId => $speciesData) {
+            foreach ($speciesData as $species => $salesDetails) {
+                // Здесь $salesDetails — это массив вида [storeSalesType1 => cost1, storeSalesType2 => cost2, …]
+                $finalResult[$typeSalesId][$species] = round(array_sum($salesDetails), 2);
+            }
+        }
+
+        return ['detail' => $resultArr, 'final' => $finalResult];
+
+
+
+    }
+
+
+    public static function getBouquetGoal($bouquet) {
+            $onlineStores = BouquetForecast::getStoresList(
+                $bouquet['id'],
+                BouquetForecast::ONLINE_STORES,
+                CityStore::class,
+                ['visible' => CityStore::IS_VISIBLE],
+                $bouquet['forecast_month'],
+                $bouquet['forecast_year']
+            );
+            $marketplaceStores = BouquetForecast::getStoresList(
+                $bouquet['id'],
+                BouquetForecast::MARKETPLACE,
+                CityStore::class,
+                ['visible' => CityStore::IS_VISIBLE],
+                $bouquet['forecast_month'],
+                $bouquet['forecast_year']
+            );
+            $offlineStores = BouquetForecast::getStoresList(
+                $bouquet['id'],
+                BouquetForecast::OFFLINE_STORES,
+                StoreType::class,
+                [],
+                $bouquet['forecast_month'],
+                $bouquet['forecast_year']
+            );
+            return [
+                'onlineStores' => $onlineStores,
+                'marketplaceStores' => $marketplaceStores,
+                'offlineStores' => $offlineStores,
+
+            ];
+}
+
 
 }
 
diff --git a/erp24/views/bouquet/month-goal.php b/erp24/views/bouquet/month-goal.php
new file mode 100644 (file)
index 0000000..a6ff09c
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/* @var $result array   // Массив с ключами 'detail' и 'final'
+@var $storesMap array // Маппинг [store_id => store_name]
+@var $month integer
+@var $year integer
+ */
+?>
+<h1>Цели на месяц: <?= $month ?>/<?= $year ?></h1>
+
+<h2>Итоговые суммы по магазинам и видам продукции</h2>
+<table border="1" cellpadding="5" cellspacing="0">
+    <thead>
+    <tr>
+        <th>Магазин</th>
+        <th>Вид продукции</th>
+        <th>Сумма</th>
+    </tr>
+    </thead>
+    <tbody>
+    <?php if (!empty($result['final'])): ?>
+        <?php foreach ($result['final'] as $storeId => $speciesData): ?>
+            <?php
+            // Определяем имя магазина по mapping'у, если оно отсутствует – выводим id
+            $storeName = isset($storesMap[$storeId]) ? $storesMap[$storeId] : $storeId;
+            ?>
+            <?php foreach ($speciesData as $species => $sum): ?>
+                <tr>
+                    <td><?= htmlspecialchars($storeName) ?></td>
+                    <td><?= htmlspecialchars($species) ?></td>
+                    <td><?= $sum ?></td>
+                </tr>
+            <?php endforeach; ?>
+        <?php endforeach; ?>
+    <?php else: ?>
+        <tr>
+            <td colspan="3">Нет данных для отображения.</td>
+        </tr>
+    <?php endif; ?>
+    </tbody>
+</table>
\ No newline at end of file