]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Merge branch 'refs/heads/develop' into feature_fomichev_erp_149_flowwow_feed
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 12 Nov 2024 07:59:01 +0000 (10:59 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 12 Nov 2024 07:59:01 +0000 (10:59 +0300)
# Conflicts:
# erp24/services/MarketplaceService.php

1  2 
erp24/services/MarketplaceService.php

index 45ddbf5fefc3fc067884361ef5d9920bc16a2ee2,ad2b1bee507a292038b02e7c91664648ee0becc9..cf075d6ca9dcdfaca8f8518ea01ce959301faf1e
@@@ -19,97 -14,46 +19,100 @@@ use yii_app\records\ProductsClass
  class MarketplaceService
  {
  
-     public static function infoForMarketplace(int $marketId, bool $is_yandex) {
 +
 +    private const CATEGORIES_WITH_SUBCATEGORIES = [
 +        "Цветы" => [
 +            "Монобукеты",
 +            "Авторские букеты",
 +            "Цветы в коробке",
 +            "Цветы в корзине",
 +            "Букеты невесты",
 +            "Композиции из цветов",
 +            "Мягкие игрушки",
 +            "Подарочные наборы",
 +            "Мишки из роз",
 +            "Открытки",
 +            "Стабилизированные цветы",
 +            "Букеты из сухоцветов",
 +            "Искусственные цветы",
 +            "Цветы в ящиках",
 +            "Другое",
 +            "Цветы поштучно",
 +            "Траурные цветы",
 +            "Букеты из мыла",
 +            "Цветы для интерьера",
 +        ],
 +        "Живые растения" => [
 +            "Цветы в горшках",
 +            "Флорариумы",
 +            "Суккуленты, кактусы",
 +            "Бонсаи",
 +            "Пальмы и деревья",
 +            "Левитирующие растения",
 +            "Саженцы и рассада",
 +            "Фитокартины",
 +            "Семена",
 +            "Другое",
 +            "Кашпо и горшки для цветов",
 +            "Наборы для выращивания",
 +            "Грунты и удобрения",
 +            "Аксессуары для комнатных растений",
 +            "Спатифиллумы",
 +            "Замиокулькасы",
 +            "Антуриумы"
 +        ]
 +    ];
 +
 -        if (!array_key_exists($marketId, MarketplaceStore::getWarehouseId()))
 -            return;
+     public static function infoForMarketplace(int $marketId) {
 +        if (!array_key_exists($marketId, MarketplaceStore::getWarehouseId())) {
 +            return null;
 +        }
  
-         $marketplacesCount = count(MarketplaceStore::getWarehouseId());
+         $is_yandex = $marketId == 2;
  
          // 1. Получение гуидов букетов
          $productsGroup = ProductsClass::find()
-             ->orWhere(['ilike', 'tip', ProductsClass::MARKETPLACE])
-             ->orWhere(['ilike', 'tip', ProductsClass::MARKETPLACE_ADDITIONAL])
+             ->where(['tip' => [ProductsClass::MARKETPLACE, ProductsClass::MARKETPLACE_ADDITIONAL]])
              ->select('category_id')
-             ->asArray();
+             ->asArray()
+             ->column();
  
          $productsGuids = Products1c::find()
-             ->andWhere(['in', 'parent_id', $productsGroup])
-             ->andWhere(['<>', 'components', ''])
-             ->select('id')
-             ->column();
+             ->where(['parent_id' => $productsGroup])
+             ->andWhere(['!=', 'components', ''])
+             ->select(['id', 'components'])
+             ->asArray()
+             ->all();
  
          // 2. Получение цен на букеты
-       //  $prices = ArrayHelper::map(Prices::findAll(['product_id' => $productsGuids]), 'product_id', 'price');
 -        $prices = ArrayHelper::map(Prices::findAll(['product_id' => ArrayHelper::getColumn($productsGuids, 'id')]), 'product_id', 'price');
++      //  $prices = ArrayHelper::map(Prices::findAll(['product_id' => ArrayHelper::getColumn($productsGuids, 'id')]), 'product_id', 'price');
 +        $allPrices = Prices::findAll(['product_id' => $productsGuids]);
 +        $prices = ArrayHelper::map($allPrices, 'product_id', 'price');
 +
 +
 +        foreach ($productsGuids as $productId) {
 +            if (!array_key_exists($productId, $prices)) {
 +                $prices[$productId] = 0;
 +            }
 +        }
  
          // 3. Получение состава букетов
          $bouquetComposition = [];
-         foreach ($productsGuids as $guid) {
-             $components = Products1c::find()
-                 ->andWhere(['id' => $guid])
-                 ->select('components')
-                 ->column();
+         $componentsGuids = [];
+         foreach ($productsGuids as $ind => $dataComponents) {
+             $guid = $dataComponents['id'];
+             $components = $dataComponents['components'];
  
              // Проверяем, что массив не пустой и строка валидна
-             if (!empty($components) && !in_array('', $components, true)) {
-                 $bouquetComposition[$guid] = json_decode($components[0]); // Сохраняем компоненты
+             if (!empty($components)) {
+                 $componentsJson = json_decode($components);
+                 $bouquetComposition[$guid] = $componentsJson;
+                 foreach ($componentsJson as $compJsonGuid => $compJsonCnt) {
+                     $componentsGuids[] = $compJsonGuid;
+                 }
              }
          }
+         $componentsGuids = array_unique($componentsGuids);
  
          // 4. Проверка остатков
  
                  $temp = intval($values['count'] / $products->$productGuid);
                  $bouquetCount = !empty($bouquetCount) ? min($bouquetCount, $temp) : $temp;
                  $store = $values['marketplace_guid'];
 -            }
 +
  
-             if (isset($bouquetCount) && $bouquetCount > 0) {
+             if (!empty($stockRecords) && isset($store) && $bouquetCount > 0) {
                  $stocks[$guid] = ['count' => $bouquetCount, 'store' => $store];
              }
 +            }
 +
          }
  
          // 5. Получение приоритетов
              }
          }
  
-         return Json::encode($availableGuids);
+         return Json::encode($distribution);
      }
 +
 +    /**
 +     * Статический метод для получения всей информации по продуктам, которая необходима для создания фида.
 +     *
 +     * @return array
 +     */
 +    public static function getAllProductsInfo($id)
 +    {
 +        $parents = ProductsClass::find()
 +            ->select('category_id')
 +            ->orWhere(['ilike', 'tip', ProductsClass::MARKETPLACE])
 +            ->orWhere(['ilike', 'tip', ProductsClass::MARKETPLACE_ADDITIONAL])
 +            ->column();
 +
 +        $products = Products1c::find()
 +            ->where(['tip' => 'products'])
 +            ->andWhere(['not', ['components' => '']])
 +            ->andWhere(['parent_id' => $parents])
 +
 +            ->all();
 +
 +        $count = (int)$id;
 +        $selectedProducts = array_slice($products, 0, $count);
 +
 +        $result = [];
 +
 +        foreach ($selectedProducts as $product) {
 +
 +            $properties = MarketplaceService::getProductPropertiesByGuid($product->id);
 +            if (!$properties) {
 +                $message = "Товар с GUID {$product->id} не имеет свойств в MatrixErpProperty и был исключен из фида.";
 +                Yii::error($message, __METHOD__);
 +
 +
 +                InfoLogService::setInfoLog(
 +                    __FILE__,
 +                    __LINE__,
 +                    $message,
 +                    'Missing properties error'
 +                );
 +                continue;
 +            }
 +
 +            $price = MarketplaceService::getProductPrice($product->id);
 +
 +
 +          /*  if ($price == 0) {
 +                $message = "У товара {$product->id} отсутствует цена и он будет исключен из фида.";
 +                Yii::error($message, __METHOD__);
 +
 +
 +                InfoLogService::setInfoLog(
 +                    __FILE__,
 +                    __LINE__,
 +                    $message,
 +                    'Zero price error'
 +                );
 +                continue;
 +            }*/
 +
 +            $components = json_decode($product->components, true);
 +            $composition = [];
 +
 +            foreach ($components as $componentId => $quantity) {
 +                $component = Products1c::findOne(['id' => $componentId]);
 +                if ($component && $quantity > 0) {
 +                    $composition[] = [
 +                        'name' => $component->name,
 +                        'quantity' => $quantity,
 +                        'unit' => 'шт'
 +                    ];
 +                }
 +            }
 +
 +            $properties = MarketplaceService::getProductPropertiesByGuid($product->id);
 +
 +            $result[] = [
 +                'id' => $product->id,
 +                'name' => $properties['displayName'],
 +                'pictures' => [$properties['imageUrl']],
 +                'price' => $price,
 +                'oldprice' => MarketplaceService::getProductOldPrice($product->id),
 +                'description' => MarketplaceService::getProductDescription($product->id),
 +                'qty' => MarketplaceService::getProductQty($product->id),
 +                'amount' => MarketplaceService::getProductQty($product->id),
 +                'weight' => MarketplaceService::getProductWeight($product->id),
 +                'minorder' => MarketplaceService::getProductMinOrder($product->id),
 +                'composition' => $composition,
 +                'available' => MarketplaceService::getProductAvailability($product->id),
 +                'category_id' => MarketplaceService::getProductCategory($product->id),
 +                'category_name' => $properties['flowwowSubcategory'],
 +                'params' => MarketplaceService::getProductParams($product->id),
 +                'productLink' => MarketplaceService::getProductLinkByGuid($product->id),
 +            ];
 +        }
 +
 +        return $result;
 +    }
 +
 +
 +    /**
 +     * Статический метод для создания XML-фида на основе информации о продуктах.
 +     *
 +     * @param array $productsInfo
 +     * @return string
 +     */
 +    public static function createXMLFeed($productsInfo)
 +    {
 +        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><yml_catalog/>');
 +        $xml->addAttribute('date', date('Y-m-d H:i'));
 +
 +        $shop = $xml->addChild('shop');
 +        $shop->addChild('name', 'Интернет магазин База Цветов 24');
 +        $shop->addChild('company', 'Интернет магазин База Цветов 24');
 +        $shop->addChild('url', 'https://bazacvetov24.ru');
 +        $shop->addChild('platform', 'BSM/Yandex/Market');
 +
 +        // Добавление валюты
 +        $currencies = $shop->addChild('currencies');
 +        $currency = $currencies->addChild('currency');
 +        $currency->addAttribute('id', 'RUB');
 +        $currency->addAttribute('rate', '1');
 +
 +        // Добавление категорий (пример добавления нескольких категорий)
 +        $uniqueCategories = [];
 +        foreach ($productsInfo as $product) {
 +            $categoryId = $product['category_id'];
 +            $categoryName = $product['category_name'];
 +
 +
 +            if (!isset($uniqueCategories[$categoryId])) {
 +                $uniqueCategories[$categoryId] = $categoryName;
 +            }
 +        }
 +
 +
 +        $categories = $shop->addChild('categories');
 +        foreach ($uniqueCategories as $id => $name) {
 +            $category = $categories->addChild('category', $name);
 +            $category->addAttribute('id', $id);
 +        }
 +
 +        // Добавление офферов (продуктов)
 +        $offers = $shop->addChild('offers');
 +        foreach ($productsInfo as $product) {
 +            $offer = $offers->addChild('offer');
 +            $offer->addAttribute('id', $product['id']);
 +            $offer->addAttribute('available', $product['available'] ? 'true' : 'false');
 +
 +            // Добавление URL продукта
 +            $offer->addChild('url',  $product['productLink']);
 +
 +            // Добавление цены и валюты
 +            $offer->addChild('price', $product['price']);
 +            $offer->addChild('oldPrice', $product['oldprice']);
 +            $offer->addChild('currencyId', 'RUB');
 +            $offer->addChild('categoryId', $product['category_id']);
 +
 +            // Добавление доступности доставки
 +            $offer->addChild('delivery', 'true');
 +
 +            // Описание продукта
 +            if (!empty($product['description'])) {
 +                $offer->addChild('description', $product['description']);
 +            }
 +
 +            // Добавление веса и количества
 +            $offer->addChild('weight', $product['weight']);
 +            //  $offer->addChild('qty', $product['qty']);
 +            // $offer->addChild('amount', $product['amount']);
 +            //   $offer->addChild('cost', $product['amount']);
 +
 +            foreach ($product['composition'] as $component) {
 +                $consist = $offer->addChild('consist', $component['quantity']);
 +                $consist->addAttribute('name', $component['name']);
 +                $consist->addAttribute('unit', $component['unit']);
 +                //   $consist->addAttribute('cost', 12);
 +            }
 +
 +            // Добавление параметров
 +            if (!empty($product['params'])) {
 +                foreach ($product['params'] as $paramName => $paramValue) {
 +                    $param = $offer->addChild('param', $paramValue);
 +                    $param->addAttribute('name', $paramName);
 +                }
 +            }
 +
 +            // Название продукта
 +            $offer->addChild('name', $product['name']);
 +
 +            // Добавление изображений продукта
 +            if (!empty($product['pictures'])) {
 +                foreach ($product['pictures'] as $picture) {
 +                    $offer->addChild('picture', $picture);
 +                }
 +            }
 +        }
 +
 +        return $xml->asXML();
 +    }
 +
 +
 +    private static function getProductPropertiesByGuid($guid) {
 +        $product = MatrixErpProperty::find()
 +            ->where(['guid' => $guid])
 +            ->one();
 +
 +        if (!$product) {
 +            return null;
 +        }
 +
 +        return [
 +            'id' => $product->id,
 +            'description' => $product->description,
 +            'imageUrl' => self::getProductImageUrl($product->image_id),
 +            'date' => $product->date,
 +            'displayName' => $product->display_name,
 +            'externalImageUrl' => $product->external_image_url,
 +            'productUrl' => $product->product_url,
 +            'flowwowCategory' => $product->flowwow_category,
 +            'flowwowSubcategory' => $product->flowwow_subcategory,
 +        ];
 +    }
 +
 +    private static function getProductImageUrl($imageId) {
 +        $image = Images::findOne($imageId);
 +        $fileName = '';
 +        if ($image && File::src($image->filename, 'images') != null) {
 +            $fileName = File::src($image->filename, 'images');
 +            return 'https://media.dev.erp-flowers.ru/media/view-url?url=' . $fileName;
 +        }
 +
 +
 +        return null;
 +    }
 +    private static function getProductLinkByGuid($guid) {
 +        return 'https://media.dev.erp-flowers.ru/media/view-card?guid=' . urlencode($guid);
 +    }
 +
 +    private static function getProductPrice($productId) {
 +        $price = Prices::find()
 +            ->where(['product_id' => $productId])
 +            ->one();
 +        return $price['price'] ?? 0;
 +    }
 +    private static function getProductOldPrice($productId) { return 300; }
 +    private static function getProductDescription($productId) {
 +
 +        $product = MatrixErpProperty::find()
 +            ->where(['guid' => $productId])
 +            ->one();
 +
 +        if (!$product) {
 +            return null; // Вернуть null, если продукт не найден
 +        }
 +
 +        return $product->description;
 +    }
 +    private static function getProductQty($productId) { return 9; }
 +    private static function getProductWeight($productId) {
 +        return 0.5;
 +    }
 +    private static function getProductCategory($productId) {
 +
 +        $product = MatrixErpProperty::find()
 +            ->where(['guid' => $productId])
 +            ->one();
 +
 +        if (!$product) {
 +            return null;
 +        }
 +
 +        return  self::getCategorySubcategoryId($product->flowwow_category, $product->flowwow_subcategory);
 +    }
 +
 +    public static function getCategorySubcategoryId($category, $subcategory)
 +    {
 +        $categories = self::CATEGORIES_WITH_SUBCATEGORIES;
 +
 +        if (!array_key_exists($category, $categories)) {
 +            return null;
 +        }
 +
 +        $categoryIndex = array_search($category, array_keys($categories)) + 1;
 +        $subcategoryIndex = array_search($subcategory, $categories[$category]) + 1;
 +
 +        if ($subcategoryIndex === false) {
 +            return null;
 +        }
 +
 +
 +        return (string)$categoryIndex . (string)$subcategoryIndex;
 +    }
 +
 +    private static function getProductMinOrder($productId) {
 +        return 1;
 +    }
 +    private static function getProductAvailability($productId) {
 +        return true;
 +    }
 +
 +    private static function getProductMaterial($productId)
 +    {
 +        // Здесь можно реализовать логику получения материала продукта
 +        return 'Цветы'; // Пример значения
 +    }
 +
 +    private static function getProductWidth($productId)
 +    {
 +        // Здесь можно реализовать логику получения ширины продукта
 +        return 18; // Пример значения
 +    }
 +
 +    private static function getProductHeight($productId)
 +    {
 +        // Здесь можно реализовать логику получения высоты продукта
 +        return 20; // Пример значения
 +    }
 +
 +    private static function getProductLength($productId)
 +    {
 +        // Здесь можно реализовать логику получения длины продукта
 +        return 9; // Пример значения
 +    }
 +
 +    private static function getProductParams($productId)
 +    {
 +        return [
 +
 +            'Ширина, См' => self::getProductWidth($productId),
 +            'Высота, См' => self::getProductHeight($productId),
 +
 +        ];
 +    }
 +
 +
 +
  }