]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Добавляем методы для получения магазинов и чеков продаж
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Mon, 3 Nov 2025 10:31:23 +0000 (13:31 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Mon, 3 Nov 2025 10:31:23 +0000 (13:31 +0300)
erp24/api2/controllers/DataTestController.php

index 33858cda320e55b55285a0fde4331967ddbb36ff..81e81971f14cd10dc57c10d682fcdb835f89b0cb 100644 (file)
@@ -93,4 +93,220 @@ class DataTestController extends BaseController {
 
         return $this->asJson(['response' => true]);
     }
+
+    /**
+     * Возвращает JSON со списком магазинов (id, name)
+     * GET /api2/data-test/get-stores
+     */
+    public function actionGetStores() {
+        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+
+        try {
+            $stores = \yii_app\records\CityStore::find()
+                ->select(['id', 'name'])
+                ->orderBy(['name' => SORT_ASC])
+                ->asArray()
+                ->all();
+
+            return $this->asJson([
+                'success' => true,
+                'data' => $stores
+            ]);
+        } catch (Exception $e) {
+            return $this->asJson([
+                'success' => false,
+                'error' => $e->getMessage()
+            ]);
+        }
+    }
+
+    /**
+     * Возвращает JSON с агрегированными покупками по дате, смене и магазину
+     * POST /api2/data-test/get-sales
+     *
+     * Тело запроса:
+     * {
+     *   "date": "2025-10-10",
+     *   "shift_type": 1,
+     *   "store_id": 5 (опционально)
+     * }
+     *
+     * shift_type:
+     * 0 = с 8:00 до 8:00 следующего дня (все)
+     * 1 = с 8:00 до 20:00 (день)
+     * 2 = с 20:00 до 8:00 (ночь)
+     */
+    public function actionGetSales() {
+        set_time_limit(300);
+        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
+
+        $request = Yii::$app->request->getRawBody();
+
+        try {
+            $input = Json::decode($request);
+        } catch (Exception $ex) {
+            return $this->asJson([
+                'success' => false,
+                'error' => 'Invalid JSON body'
+            ]);
+        }
+
+        // Валидация обязательных параметров
+        if (empty($input['date'])) {
+            return $this->asJson([
+                'success' => false,
+                'error' => 'Date is required'
+            ]);
+        }
+
+        $date = $input['date'];
+        $shiftType = $input['shift_type'] ?? 0;
+        $storeIdFilter = $input['store_id'] ?? null;
+
+        try {
+            // Определяем диапазон времени для смены
+            $dateObj = new \DateTime($date);
+            $currentDateStr = $dateObj->format('Y-m-d');
+
+            // Получаем дату следующего дня
+            $nextDateObj = clone $dateObj;
+            $nextDateStr = $nextDateObj->modify('+1 day')->format('Y-m-d');
+
+            $dayStart = $currentDateStr . ' 08:00:00';
+            $dayEnd = $currentDateStr . ' 20:00:00';
+            $nightStart = $currentDateStr . ' 20:00:00';
+            $nightEnd = $currentDateStr . ' 23:59:59';
+            $nextDayStart = $nextDateStr . ' 00:00:00';
+            $nextDayEnd = $nextDateStr . ' 08:00:00';
+
+            // Построение базового запроса продаж
+            $query = \yii_app\records\Sales::find()
+                ->where(['or', ['order_id' => ''], ['order_id' => 0]]) // Только офлайн продажи
+                ->orderBy(['store_id' => SORT_ASC, 'date' => SORT_ASC]);
+
+            // Фильтр по смене
+            if ($shiftType === 1) {
+                // День: 8:00 - 20:00
+                $query->andWhere(['between', 'date', $dayStart, $dayEnd]);
+            } elseif ($shiftType === 2) {
+                // Ночь: 20:00 - 8:00 следующего дня
+                $query->andWhere(['OR',
+                    ['between', 'date', $nightStart, $nightEnd],
+                    ['between', 'date', $nextDayStart, $nextDayEnd]
+                ]);
+            } else {
+                // Все смены (вся дата)
+                $query->andWhere(['between', 'date', $currentDateStr . ' 00:00:00', $currentDateStr . ' 23:59:59']);
+            }
+
+            // Фильтр по магазину если задан
+            if (!empty($storeIdFilter)) {
+                $query->andWhere(['store_id' => $storeIdFilter]);
+            }
+
+            $sales = $query->with('products')->asArray()->all();
+
+            if (empty($sales)) {
+                return $this->asJson([
+                    'success' => true,
+                    'data' => []
+                ]);
+            }
+
+            // Агрегируем данные и присоединяем информацию о товарах
+            $aggregated = [];
+            $storeRegions = [];
+
+            foreach ($sales as $sale) {
+                $saleStoreId = $sale['store_id'];
+
+                // Кэшируем регион магазина
+                if (!isset($storeRegions[$saleStoreId])) {
+                    $storeParams = \yii_app\records\CityStoreParams::findOne(['store_id' => $saleStoreId]);
+                    $storeRegions[$saleStoreId] = $storeParams ? $storeParams->address_region : null;
+                }
+
+                $saleKey = $saleStoreId . '_' . $sale['date']; // Ключ для агрегации
+
+                if (!isset($aggregated[$saleKey])) {
+                    $aggregated[$saleKey] = [
+                        'id' => $sale['id'],
+                        'date' => $sale['date'],
+                        'store_id' => (int)$saleStoreId,
+                        'summ' => (float)$sale['summ'],
+                        'operation' => $sale['operation'],
+                        'status' => $sale['status'],
+                        'skidka' => (float)$sale['skidka'],
+                        'products' => []
+                    ];
+                } else {
+                    // Суммируем значения
+                    $aggregated[$saleKey]['summ'] += (float)$sale['summ'];
+                    $aggregated[$saleKey]['skidka'] += (float)$sale['skidka'];
+                }
+
+                // Получаем товары из этого чека
+                $products = \yii_app\records\SalesProducts::find()
+                    ->where(['check_id' => $sale['id']])
+                    ->asArray()
+                    ->all();
+
+                foreach ($products as $product) {
+                    // Получаем информацию о товаре
+                    $productInfo = \yii_app\records\Products1c::find()
+                        ->where(['id' => $product['product_id']])
+                        ->select(['id', 'name'])
+                        ->asArray()
+                        ->one();
+
+                    // Получаем актуальную цену товара
+                    $regionId = $storeRegions[$saleStoreId];
+                    $priceQuery = \yii_app\records\PricesDynamic::find()
+                        ->where(['product_id' => $product['product_id']])
+                        ->andWhere(['active' => \yii_app\records\PricesDynamic::ACTIVE]);
+
+                    // Приоритет: сначала ищем с регионом, потом без
+                    if ($regionId) {
+                        $priceQuery->andWhere(['region_id' => $regionId]);
+                    }
+
+                    $priceData = $priceQuery->select(['price'])
+                        ->orderBy(['date_from' => SORT_DESC])
+                        ->asArray()
+                        ->one();
+
+                    $productData = [
+                        'product_id' => $product['product_id'],
+                        'name' => $productInfo['name'] ?? 'Unknown',
+                        'quantity' => (float)$product['quantity'],
+                        'price' => $priceData ? (float)$priceData['price'] : (float)$product['price'],
+                        'discount' => (float)$product['discount'],
+                        'summ' => (float)$product['summ']
+                    ];
+
+                    $aggregated[$saleKey]['products'][] = $productData;
+                }
+            }
+
+            // Группируем по магазину
+            $grouped = [];
+            foreach ($aggregated as $sale) {
+                $storeId = $sale['store_id'];
+                // Убираем store_id из объекта продажи, так как он будет в ключе
+                unset($sale['store_id']);
+                $grouped[$storeId][] = $sale;
+            }
+
+            return $this->asJson([
+                'success' => true,
+                'data' => $grouped
+            ]);
+
+        } catch (Exception $e) {
+            return $this->asJson([
+                'success' => false,
+                'error' => $e->getMessage()
+            ]);
+        }
+    }
 }