]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Правки по загрузке
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 2 Sep 2025 09:53:10 +0000 (12:53 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 2 Sep 2025 09:53:10 +0000 (12:53 +0300)
erp24/actions/marketplace/ReportAction.php
erp24/controllers/MatrixErpController.php
erp24/records/Images.php
erp24/records/MatrixErpProperty.php
erp24/services/ProductParserService.php

index 5c86dec8bb3df8b965058dcdc3d6a95d34633666..5bd262d901a04ff24e15b547f123ccc935b2dae6 100644 (file)
@@ -33,10 +33,10 @@ class ReportAction extends Action
             'flowwow_category' => 'string',
             'flowwow_subcategory' => 'string',
             'yandex_category' => 'string',
-            'length' => 'numeric',
+            //'length' => 'numeric',
             'width' => 'numeric',
             'height' => 'numeric',
-            'weight' => 'numeric',
+            //'weight' => 'numeric',
         ];
 
         $conditions = [];
index a093b2f3e08c1a2e67f0a59793f9fb0012866f97..c074271405da8d13f57c0a9ce90c086176c7b330 100644 (file)
@@ -292,7 +292,7 @@ class MatrixErpController extends Controller
 
             if ($model->validate()) {
                 foreach ($model->files as $file) {
-                    $results[] = $this->processFile($file, $model->category);
+                    $results[] = $this->processFile($file, $model->category, $model->subcategory);
                 }
 
                 Yii::$app->session->setFlash('importResults', $results);
@@ -309,7 +309,7 @@ class MatrixErpController extends Controller
     /**
      * Обработка одного файла: парсинг → поиск MatrixErp по артикулу → upsert MatrixErpProperty по GUID.
      */
-    protected function processFile(UploadedFile $file, string $category): array
+    protected function processFile(UploadedFile $file, string $category, string $subcategory): array
     {
         $res = [
             'file' => $file->name,
@@ -325,16 +325,15 @@ class MatrixErpController extends Controller
             $service = new ProductParserService();
 
             $parsed = $service->parseProductHtml($html);
-
             $products = $this->normalizeParsed($parsed);
-            var_dump($products);die();
+
             if (empty($products)) {
                 throw new \RuntimeException('Парсер вернул пустой результат.');
             }
 
             foreach ($products as $p) {
                 $art = $this->extractArticule($p['name'] ?? '');
-                $res['articule'] = $res['articule'] ?? $art;
+                $res['articule'] = $art ?? $res['articule'];
 
                 if (!$art) {
                     $res['status'] = 'error';
@@ -351,7 +350,7 @@ class MatrixErpController extends Controller
 
                 $res['guid'] = $matrix->guid;
 
-                if (!$this->upsertProperty($matrix, $p, $category)) {
+                if (!$this->upsertProperty($matrix, $p, $category, $subcategory)) {
                     $res['status'] = 'error';
                     $res['errors'][] = "Не удалось сохранить свойства для GUID {$matrix->guid}.";
                 }
@@ -383,14 +382,16 @@ class MatrixErpController extends Controller
     }
 
     /**
-     * Артикул из названия: ищем (FW0125) или просто FW0125, либо "Артикул: FW0125".
+     * Артикул из названия: ищем (FW0125)
      */
     protected function extractArticule(string $name): ?string
     {
-        $pattern = `/\\((?[A-Z]{2,4}\\d{3,6})\\)/u`;
-            if (preg_match($pattern, $name, $m)) {
-                return strtoupper($m['art']);
-            }
+
+        if ($name) {
+            $nameStringArray = explode('(', $name);
+            $articule = trim(explode(')', $nameStringArray[1])[0]);
+            return $articule;
+        }
 
         return null;
     }
@@ -400,74 +401,68 @@ class MatrixErpController extends Controller
      */
     protected function upsertProperty(MatrixErp $matrix, array $matrixProduct, string $category, string $subcategory): bool
     {
-        $prop = MatrixErpProperty::find()->where(['guid' => $matrix->guid])->one();
-        $nowDt = date('Y-m-d H:i:s');
-        $nowD = date('Y-m-d');
-
-        if (!$prop) {
-            $prop = new MatrixErpProperty();
-            $prop->guid = $matrix->guid;
-            $prop->matrix_erp_id = $matrix->guid;
-            $prop->date = $nowD;
-            $prop->created_admin_id = Yii::$app->user->id ?? null;
-            $prop->created_at = $nowDt;
+        $matrixProductProperty = MatrixErpProperty::find()->where(['guid' => $matrix->guid])->one();
+        $date = date('Y-m-d H:i:s');
+
+        if (!$matrixProductProperty) {
+            $matrixProductProperty = new MatrixErpProperty();
+            $matrixProductProperty->guid = $matrix->guid;
+            $matrixProductProperty->date = $date;
+            $matrixProductProperty->created_admin_id = Yii::$app->user->id ?? null;
+            $matrixProductProperty->created_at = $date;
         } else {
-            $prop->updated_admin_id = Yii::$app->user->id ?? null;
-            $prop->updated_at = $nowDt;
+            $matrixProductProperty->updated_admin_id = Yii::$app->user->id ?? null;
+            $matrixProductProperty->updated_at = $date;
         }
 
-            try {
-                $uploadImage = FileService::downloadAsUploadedFile($externalUrl, maxBytes: 8_000_000);
-            } catch (\Throwable $e) {
-                Yii::error("Ошибка загрузки изображения по ссылке: " . $e->getMessage());
-
-                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
-                return ['error' => 'Не удалось скачать файл по ссылке'];
-            }
+        try {
+            $uploadImage = FileService::downloadAsUploadedFile($matrixProduct['image_url']);
+        } catch (\Throwable $e) {
+            Yii::error("Ошибка загрузки изображения по ссылке: " . $e->getMessage());
+        }
 
 
         if ($uploadImage) {
             if (Images::isImageFile($uploadImage, ['png', 'jpg', 'jpeg', 'webp', 'gif'])) {
                 $image = new Images();
-                $imageId = $image->loadImage($uploadImage); // ваш существующий метод (как при обычной загрузке)
+                $imageId = $image->loadImage($uploadImage);
 
                 if (!empty($imageId)) {
-                    $prop->image_id = $imageId;
-                    $prop->external_image_url = MarketplaceService::getProductImageUrl($imageId);
+                    $matrixProductProperty->image_id = $imageId;
+                    $matrixProductProperty->external_image_url = MarketplaceService::getProductImageUrl($imageId);
                     if (!empty($oldFile)) {
                         $oldFile->delete();
                     }
-                    if (!$prop->save()) {
-                        Yii::error("Ошибка сохранения ссылок на картинки " . json_encode($modelEdit->getErrors(), JSON_UNESCAPED_UNICODE));
+                    if (!$matrixProductProperty->save()) {
+                        Yii::error("Ошибка сохранения ссылок на картинки " . json_encode($matrixProductProperty->getErrors(), JSON_UNESCAPED_UNICODE));
                     }
                 }
             } else {
-                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
-                return ['error' => 'Файл не является изображением либо запрещённое расширение'];
+                Yii::error(json_encode(['error' => 'Файл не является изображением либо запрещённое расширение'], JSON_UNESCAPED_UNICODE));
+                return false;
             }
         } else {
-            \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
-            return ['error' => 'Не передан файл и не указана ссылка'];
+            Yii::error(json_encode(['error' => 'Не передан файл и не указана ссылка'], JSON_UNESCAPED_UNICODE));
+            return false;
         }
 
 
-        $prop->display_name = $matrixProduct['name'] ?? $prop->display_name;
-        $prop->description = $matrixProduct['description'] ?? $prop->description;
-        $prop->external_image_url = $matrixProduct['image_url'] ?? $prop->external_image_url;
-        $prop->product_url = $matrixProduct['product_url'] ?? $prop->product_url;
+        $matrixProductProperty->display_name = $matrixProduct['name'];
+        $matrixProductProperty->description = $matrixProduct['description'];
+
+        $matrixProductProperty->product_url = MarketplaceService::getProductLinkByGuid($matrixProductProperty->guid);
 
         // Категории
-        $prop->flowwow_category = $category;
-        $prop->flowwow_subcategory = $category;
-        $prop->flowwow_subcategory = $matrixProduct['properties']['subcategory'] ?? $prop->flowwow_subcategory;
-        $prop->yandex_category = $matrixProduct['properties']['yandex_category'] ?? $prop->yandex_category;
+        $matrixProductProperty->flowwow_category = $category;
+        $matrixProductProperty->flowwow_subcategory = $subcategory;
+        $matrixProductProperty->yandex_category = "Цветы, букеты, композиции";
+
+
 
+        if (isset($matrixProduct['properties']['Размер']['ширина'])) $matrixProductProperty->width = (float)$matrixProduct['properties']['Размер']['ширина'];
+        if (isset($matrixProduct['properties']['Размер']['высота'])) $matrixProductProperty->height = (float)$matrixProduct['properties']['Размер']['высота'];
 
-        if (isset($matrixProduct['properties']['length'])) $prop->length = (float)$matrixProduct['properties']['length'];
-        if (isset($matrixProduct['properties']['width'])) $prop->width = (float)$matrixProduct['properties']['width'];
-        if (isset($matrixProduct['properties']['height'])) $prop->height = (float)$matrixProduct['properties']['height'];
-        if (isset($matrixProduct['properties']['weight'])) $prop->weight = (float)$matrixProduct['properties']['weight'];
 
-        return $prop->save();
+        return $matrixProductProperty->save();
     }
 }
\ No newline at end of file
index 67210757169b38e76e6da91560caa4ecf8684683..01460daa121edf725fb7c411452160b8a5251860 100644 (file)
@@ -94,7 +94,7 @@ class Images extends \yii\db\ActiveRecord
             mkdir($imageDirPath);
         }
 
-        if ($file_obj->saveAs($imageDirPath . '/' . $file_name)) {
+        if ($file_obj->saveAs($imageDirPath . '/' . $file_name, false)) {
             $this->original_name = $file_obj->baseName;
             $this->filename = $file_name;
             $this->size = $file_obj->size;
index b65840ca52d97c6a4f6dd182ac54f65851f2bf31..83a8e4e010672bf1263168af87f6026be518cb63 100644 (file)
@@ -8,7 +8,6 @@ use Yii;
  * This is the model class for table "matrix_erp_property".
  *
  * @property int $id ID
- * @property string $matrix_erp_id
  * @property string $guid
  * @property string|null $description Описание
  * @property int|null $image_id Изображение
index 7f7e6b934432dcf31d5b6e37c4ff47d698572396..d05f2fa0bf783a6e818c1d36f9502e5c0ce14a8b 100644 (file)
@@ -17,55 +17,23 @@ class ProductParserService {
 
         return [
             'name' => $this->extractName($xpath),
-            'price' => $this->extractPrice($xpath),
-            'old_price' => $this->extractOldPrice($xpath),
-            'rating' => $this->extractRating($xpath),
-            'reviews_count' => $this->extractReviewsCount($xpath),
             'image_url' => $this->extractImageUrl($xpath),
             'description' => $this->extractDescription($xpath),
             'properties' => $this->extractProperties($xpath),
-
         ];
     }
 
-    private
-    function extractName(DOMXPath $xpath): string
+    private function extractName(DOMXPath $xpath): string
     {
         $node = $xpath->query("//h1")->item(0);
         return $node ? trim($node->nodeValue) : '';
     }
 
-    private
-    function extractPrice(DOMXPath $xpath): string
-    {
-        $node = $xpath->query("//span[@class='footer-price']")->item(0);
-        return $node ? trim($node->nodeValue) : '';
-    }
-
-    private
-    function extractOldPrice(DOMXPath $xpath): string
-    {
-        $node = $xpath->query("//div[@class='footer-old-price']")->item(0);
-        return $node ? trim($node->nodeValue) : '';
-    }
 
 
-    private
-    function extractRating(DOMXPath $xpath): string
-    {
-        $node = $xpath->query("//div[@class='rating']//div[contains(@class, 'el-rate')]")->item(0);
-        return $node ? $node->getAttribute('data-score') : '';
-    }
 
-    private
-    function extractReviewsCount(DOMXPath $xpath): string
-    {
-        $node = $xpath->query("//div[@class='review-count']")->item(0);
-        return $node ? trim($node->nodeValue) : '';
-    }
 
-    private
-    function extractImageUrl(DOMXPath $xpath): string
+    private function extractImageUrl(DOMXPath $xpath): string
     {
         $q1 = "//div[@id='js-detect-events']" .
             "//div[contains(concat(' ', normalize-space(@class), ' '), ' swiper-slide-active ')]" .
@@ -92,14 +60,18 @@ class ProductParserService {
         return $src;
     }
 
-    private
-    function extractDescription(DOMXPath $xpath): string
+    private function extractDescription(DOMXPath $xpath): string
     {
-        $node = $xpath->query("//div[@class='product-properties-general']" . "//div[@class='property-item']" .  "//p[@class='pre-line']" . "//span")->item(0);
+        $expression =
+            "//*[contains(concat(' ', normalize-space(@class), ' '), ' product-properties-general ')]" .
+            "//*[contains(concat(' ', normalize-space(@class), ' '), ' property-item ')]" .
+            "//*[contains(concat(' ', normalize-space(@class), ' '), ' pre-line ')]//span";
+
+        $node = $xpath->query($expression)->item(0);
         return $node ? trim($node->nodeValue) : '';
     }
 
-    function extractProperties(DOMXPath $xpath): array
+    private function extractProperties(DOMXPath $xpath): array
     {
         $properties = [];
 
@@ -133,40 +105,10 @@ class ProductParserService {
 
                 if ($sizes) {
                     $properties['Размер'] = $sizes;
-                    if (isset($sizes['Ширина'])) $properties['width']  = $sizes['Ширина'];
-                    if (isset($sizes['Высота'])) $properties['height'] = $sizes['Высота'];
                 }
 
-                continue;
-            }
-
-
-            $valueNode = $xpath->query(
-                ".//*[contains(concat(' ', normalize-space(@class), ' '), ' property-text ') " .
-                "   or contains(concat(' ', normalize-space(@class), ' '), ' pre-line ')]",
-                $node
-            )->item(0);
-
-            if ($valueNode) {
-                $properties[$propName] = trim(preg_replace('/\s+/u', ' ', $valueNode->textContent));
             }
-        }
-
 
-        if (!isset($properties['width']) || !isset($properties['height'])) {
-            $tagSpans = $xpath->query("//ul[contains(@class,'size-tag')]//li//span[not(contains(@class,'size-tag-icon'))]");
-            $seen = [];
-            foreach ($tagSpans as $span) {
-                $text = trim($span->textContent);
-                if (preg_match('/(\d+(?:[.,]\d+)?)\s*см/ui', $text, $m)) {
-                    $val = (float) str_replace(',', '.', $m[1]);
-                    $seen[] = $val;
-                }
-            }
-            if (!empty($seen)) {
-                if (!isset($properties['width'])  && isset($seen[0])) $properties['width']  = $seen[0];
-                if (!isset($properties['height']) && isset($seen[1])) $properties['height'] = $seen[1];
-            }
         }
 
         return $properties;