class MarketplaceService
{
- // Порядок основных категорий (Цветы, Живые растения) не менять, добавлять в конец массива
+ // Порядок основных категорий (Цветы, Живые растения) не менять, добавлять в конец массива
private const CATEGORIES_WITH_SUBCATEGORIES = [
"Цветы" => [
1 => "Монобукеты",
self::SUBJECT_DELIVERED => 5,
];
- public static function infoForMarketplace(int $marketId) {
+ public static function infoForMarketplace(int $marketId)
+ {
if (!array_key_exists($marketId, MarketplaceStore::getWarehouseId()))
return;
// 2. Получение цен на букеты
$prices = ArrayHelper::map(Prices::findAll(['product_id' => ArrayHelper::getColumn($productsGuids, 'id')]), 'product_id', 'price');
- /* $allPrices = Prices::findAll(['product_id' => $productsGuidsIds]);
-
- if (empty($allPrices)) {
- Yii::warning('Не найдено цен для GUID.');
- }
+ /* $allPrices = Prices::findAll(['product_id' => $productsGuidsIds]);
- $prices = ArrayHelper::map($allPrices, 'product_id', 'price') ?: []; // Ensure $prices is an array
+ if (empty($allPrices)) {
+ Yii::warning('Не найдено цен для GUID.');
+ }
- foreach ($productsGuidsIds as $productId) {
- // Ensure $productId is scalar before checking
- if (is_scalar($productId) && !array_key_exists($productId, $prices)) {
- $prices[$productId] = 0;
- } elseif (!is_scalar($productId)) {
- Yii::warning('Invalid productId type: ' . gettype($productId));
- }
- }*/
+ $prices = ArrayHelper::map($allPrices, 'product_id', 'price') ?: []; // Ensure $prices is an array
+ foreach ($productsGuidsIds as $productId) {
+ // Ensure $productId is scalar before checking
+ if (is_scalar($productId) && !array_key_exists($productId, $prices)) {
+ $prices[$productId] = 0;
+ } elseif (!is_scalar($productId)) {
+ Yii::warning('Invalid productId type: ' . gettype($productId));
+ }
+ }*/
// 3. Получение состава букетов
}
}
}
- // var_dump($distribution);
+ // var_dump($distribution);
return $distribution;
}
- public static function getMarketplaceProducts() {
+ public static function getMarketplaceProducts()
+ {
$productsGroup = ProductsClass::find()
->where(['tip' => [ProductsClass::MARKETPLACE, ProductsClass::MARKETPLACE_ADDITIONAL]])
->select('category_id')
return $products;
}
+
/**
* Статический метод для получения всей информации по продуктам, которая необходима для создания фида.
*
->where(['tip' => 'products'])
->andWhere(['not', ['components' => '']])
->andWhere(['parent_id' => $parents])
-
->all();
$count = (int)$id;
if ($price == 0) {
$message = "У товара {$product->id} отсутствует цена и он будет исключен из фида.";
Yii::error($message, __METHOD__);
- InfoLogService::setInfoLog(
+ InfoLogService::setInfoLog(
__FILE__,
__LINE__,
$message,
$result = [];
foreach ($products as $product) {
- $check = self::checkProducts($product);
- if ($check === false) {
- continue;
+ $properties = MarketplaceService::getProductPropertiesByGuid($product->id);
+ if (!$properties) {
+ $message = "Товар с GUID {$product->id} не имеет свойств в MatrixErpProperty и был исключен из фида.";
+ Yii::error($message, __METHOD__);
+
+ InfoLogService::setInfoLog(
+ __FILE__,
+ __LINE__,
+ $message,
+ 'Missing properties error'
+ );
}
- $properties = $check['properties'];
- $price = $check['price'];
+ $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 = [];
return $result;
}
-
+
public function checkProducts($product, $isView = false): array|false
{
$properties = MarketplaceService::getProductPropertiesByGuid($product->id);
$offer->addAttribute('available', $product['available'] ? 'true' : 'false');
// Добавление URL продукта
- $offer->addChild('url', $product['productLink']);
+ $offer->addChild('url', $product['productLink']);
// Добавление цены и валюты
$offer->addChild('price', $product['price']);
- // $offer->addChild('oldPrice', $product['oldprice']);
+ // $offer->addChild('oldPrice', $product['oldprice']);
$offer->addChild('currencyId', 'RUB');
$offer->addChild('categoryId', $product['category_id']);
}
// Добавление веса и количества
- if (isset($product['weight']) ) {
+ if (isset($product['weight'])) {
$offer->addChild('weight', $product['weight']);
}
if (!(isset($product['category_id']) && str_starts_with((string)$product['category_id'], '1'))) {
}
-
// Добавление изображений продукта
if (!empty($product['pictures'])) {
foreach ($product['pictures'] as $picture) {
}
- private static function getProductPropertiesByGuid($guid) {
+ private static function getProductPropertiesByGuid($guid)
+ {
$product = MatrixErpProperty::find()
->where(['guid' => $guid])
->one();
];
}
- private static function getProductImageUrl($imageId) {
+ private static function getProductImageUrl($imageId)
+ {
$image = Images::findOne($imageId);
$fileName = '';
if ($image && File::src($image->filename, 'images') != null) {
return null;
}
- private static function getProductLinkByGuid($guid) {
+
+ private static function getProductLinkByGuid($guid)
+ {
return 'https://media.erp-flowers.ru/media/view-card?guid=' . urlencode($guid);
}
- private static function getProductPrice($productId) {
+ 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) {
+
+ private static function getProductOldPrice($productId)
+ {
+ return 300;
+ }
+
+ private static function getProductDescription($productId)
+ {
$product = MatrixErpProperty::find()
->where(['guid' => $productId])
return $product->description;
}
- private static function getProductQty($productId) { return 9; }
- private static function getProductWeight($productId) {
+
+ private static function getProductQty($productId)
+ {
+ return 9;
+ }
+
+ private static function getProductWeight($productId)
+ {
$product = MatrixErpProperty::find()
->where(['guid' => $productId])
->one();
return $product->weight ?? 0.5;
}
- private static function getProductCategory($productId) {
+
+ private static function getProductCategory($productId)
+ {
$product = MatrixErpProperty::find()
->where(['guid' => $productId])
return null;
}
- return self::getCategorySubcategoryId($product->flowwow_category, $product->flowwow_subcategory);
+ return self::getCategorySubcategoryId($product->flowwow_category, $product->flowwow_subcategory);
}
public static function getCategorySubcategoryId($category, $subcategory)
return (string)$categoryIndex . (string)$subcategoryIndex;
}
- private static function getProductMinOrder($productId) {
+ private static function getProductMinOrder($productId)
+ {
return 1;
}
- private static function getProductAvailability($availableQty) {
+
+ private static function getProductAvailability($availableQty)
+ {
return $availableQty > 0;
}
];
}
+
/**
* Получает данные о заказах для указанных кампаний с учетом фильтров.
*
- * @param array $campaignIds Массив идентификаторов кампаний (warehouse_guid).
- * @param string|null $status Фильтр по статусу заказа (например, "DELIVERED").
- * @param string|null $substatus Фильтр по подстатусу заказа (например, "CANCELLED").
- * @param string $fromDate Начальная дата в формате "дд-мм-гггг".
- * @param string|null $toDate Конечная дата в формате "дд-мм-гггг".
+ * @param array $campaignIds Массив идентификаторов кампаний (warehouse_guid).
+ * @param string|null $status Фильтр по статусу заказа (например, "DELIVERED").
+ * @param string|null $substatus Фильтр по подстатусу заказа (например, "CANCELLED").
+ * @param string $fromDate Начальная дата в формате "дд-мм-гггг".
+ * @param string|null $toDate Конечная дата в формате "дд-мм-гггг".
*
* @return array Массив заказов, сгруппированных по кампании.
*/
* возвращая данные в виде массива, где ключ – идентификатор кампании (магазина),
* а значение – массив заказов (в данном случае с одним заказом).
*
- * @param int $campaignId Идентификатор кампании (магазина) в API.
- * @param int $orderId Идентификатор заказа.
+ * @param int $campaignId Идентификатор кампании (магазина) в API.
+ * @param int $orderId Идентификатор заказа.
* @param string|null $contentType Заголовок Content-Type. Если не передан, используется значение по умолчанию.
*
* @return array Массив заказов в виде: [ $campaignId => [ $order ] ]
}
}
}
- // проверяем и устанавливаем ready_to = 1
- $baseUrl = "https://partner.market.yandex.ru/order/";
- $marketplaceOrder->order_link = $baseUrl . $marketplaceOrder->marketplace_order_id . "?tld=ru&partnerId=197274828";
- if (!$marketplaceOrder->save()) {
- Yii::error(
- 'Ошибка сохранения заказа при создании ссылки: ' . json_encode(
- $marketplaceOrder->getErrors(),
- JSON_UNESCAPED_UNICODE
- )
- );
- }
- self::setReadyMarketplaceOrders($marketplaceOrder);
+ // проверяем и устанавливаем ready_to = 1
+ $baseUrl = "https://partner.market.yandex.ru/order/";
+ $marketplaceOrder->order_link = $baseUrl . $marketplaceOrder->marketplace_order_id . "?tld=ru&partnerId=197274828";
+ if (!$marketplaceOrder->save()) {
+ Yii::error(
+ 'Ошибка сохранения заказа при создании ссылки: ' . json_encode(
+ $marketplaceOrder->getErrors(),
+ JSON_UNESCAPED_UNICODE
+ )
+ );
+ }
+ self::setReadyMarketplaceOrders($marketplaceOrder);
} else {
Yii::error(
'Ошибка сохранения заказа: ' . json_encode(
* Получает данные о возврате заказа через ReturnsApi.
*
* @param int $campaignId Идентификатор кампании (магазина).
- * @param int $orderId Идентификатор заказа.
- * @param int $returnId Идентификатор возврата.
+ * @param int $orderId Идентификатор заказа.
+ * @param int $returnId Идентификатор возврата.
*
* @return array Массив с данными возврата:
* - 'returnedAt': Время создания возврата (ISO 8601).
$returnedAt = $returnResult->getCreationDate();
$rawReturnData = json_encode($returnResponse);
return [
- 'returnedAt' => $returnedAt,
+ 'returnedAt' => $returnedAt,
'rawReturnData' => $rawReturnData,
];
} catch (\Exception $e) {
$progressCallback = null,
$seen = false,
$unseen = false
- ) {
+ )
+ {
imap_errors();
- imap_alerts();
+ imap_alerts();
$debugMode = true;
set_time_limit(300);
if (!$date) {
//$date = date('d-M-Y');
- $sinceDate = date('d-M-Y',strtotime("-1 day"));
- $beforeDate = date('d-M-Y',strtotime("+1 day"));
+ $sinceDate = date('d-M-Y', strtotime("-1 day"));
+ $beforeDate = date('d-M-Y', strtotime("+1 day"));
$searchCriteria = 'SINCE "' . $sinceDate . '" BEFORE "' . $beforeDate . '"';
} else {
- $sinceDate = date('d-M-Y',strtotime("{$date} -1 day"));
- $beforeDate = date('d-M-Y',strtotime("{$date} +1 day"));
+ $sinceDate = date('d-M-Y', strtotime("{$date} -1 day"));
+ $beforeDate = date('d-M-Y', strtotime("{$date} +1 day"));
if ($useSince) {
$searchCriteria = 'SINCE ';
$searchCriteria .= '"' . $date . '" ';
if ($progressCallback) {
call_user_func($progressCallback, "Поиск писем в папке: $folder...");
}
- // self::imap_debug_log("Поисковой запрос: {$searchCriteria}", $debugMode, $progressCallback);
+ // self::imap_debug_log("Поисковой запрос: {$searchCriteria}", $debugMode, $progressCallback);
$emails = imap_search($inbox, $searchCriteria);
self::check_imap_errors($debugMode, $progressCallback);
$email->date = $date;
$email->body = $body;
$email->created_at = date('Y-m-d H:i:s');
-
+
if ($email->save()) {
return $email;
} else {
}
- public static function imap_debug_log($message, $debugMode, $progressCallback) {
+ public static function imap_debug_log($message, $debugMode, $progressCallback)
+ {
if ($debugMode) {
if ($progressCallback) {
}
}
- public static function check_imap_errors($debugMode, $progressCallback) {
+ public static function check_imap_errors($debugMode, $progressCallback)
+ {
$errors = imap_errors();
$alerts = imap_alerts();
{
$count = 0;
if ($message) {
- $store = MarketplaceStore::getWarehouseGuidByAccountEmail($message['to']) ?? 206008;
-
- $order = self::getOrdersDataFromMessage($message);
-
- if ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_NEW]) {
- $statusCode = 'PROCESSING';
- $substatusCode = 'STARTED';
- } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_APPROVED]) {
- $statusCode = 'PROCESSING';
- $substatusCode = 'APPROVED';
- } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_CANCELLED]) {
- $statusCode = 'CANCELLED';
- $substatusCode = 'USER_CHANGED_MIND';
- } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_CHANGED]) {
- $statusCode = 'PROCESSING';
- $substatusCode = 'CHANGED';
- } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_DELIVERED]) {
- $statusCode = 'DELIVERED';
- $substatusCode = 'DELIVERY_SERVICE_DELIVERED';
- }
- $count = self::processFlowwowOrders($order, $store, $statusCode, $substatusCode, $message['subject_index']);
+ $store = MarketplaceStore::getWarehouseGuidByAccountEmail($message['to']) ?? 206008;
+
+ $order = self::getOrdersDataFromMessage($message);
+
+ if ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_NEW]) {
+ $statusCode = 'PROCESSING';
+ $substatusCode = 'STARTED';
+ } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_APPROVED]) {
+ $statusCode = 'PROCESSING';
+ $substatusCode = 'APPROVED';
+ } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_CANCELLED]) {
+ $statusCode = 'CANCELLED';
+ $substatusCode = 'USER_CHANGED_MIND';
+ } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_CHANGED]) {
+ $statusCode = 'PROCESSING';
+ $substatusCode = 'CHANGED';
+ } elseif ($message['subject_index'] == self::SUBJECT_INDEX[self::SUBJECT_DELIVERED]) {
+ $statusCode = 'DELIVERED';
+ $substatusCode = 'DELIVERY_SERVICE_DELIVERED';
+ }
+ $count = self::processFlowwowOrders($order, $store, $statusCode, $substatusCode, $message['subject_index']);
}
return $count;
}
if ($clientText) {
- $orderDetails['client'] = str_replace('Позвонить', '', $clientText);
+ $orderDetails['client'] = str_replace('Позвонить', '', $clientText);
}
$recipientBlock = $main->findOne('p:contains("Получатель")');
$itemsBlock = false;
if ($main->findOneOrFalse('table h2:contains("Детали заказа")') != false) {
$itemsBlock = $main->findOneOrFalse('table h2:contains("Детали заказа")');
- // Yii::warning('Детали заказа 1: ' . json_encode($itemsBlock->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__);
+ // Yii::warning('Детали заказа 1: ' . json_encode($itemsBlock->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__);
} elseif ($main->findOneOrFalse('table p:contains("Детали заказа")') != false) {
$itemsBlock = $main->findOneOrFalse('table p:contains("Детали заказа")');
- // Yii::warning('Детали заказа 2: ' . json_encode($itemsBlock->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__);
+ // Yii::warning('Детали заказа 2: ' . json_encode($itemsBlock->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__);
}
if ($itemsBlock) {
Yii::warning('Детали заказа 3: ' . json_encode($itemsBlock->parentNode()->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__);
- // $itemsTable = $itemsBlock->parentNode()->find('table', 2);
+ // $itemsTable = $itemsBlock->parentNode()->find('table', 2);
$itemsTable = $itemsBlock->parentNode();
$itemsRows = $itemsTable->find('tr');
// Извлекаем название и количество из второго <td>
$tds = $itemsRow->find('td');
if (count($tds) >= 2) {
- $itemData['name'] = trim(str_replace("\u{00A0}", ' ', strip_tags(preg_replace('/\s+/', ' ',$tds[1]->find('p', 0)->innerText()))));
+ $itemData['name'] = trim(str_replace("\u{00A0}", ' ', strip_tags(preg_replace('/\s+/', ' ', $tds[1]->find('p', 0)->innerText()))));
$itemData['count'] = trim(str_replace(["\u{00A0}", 'шт.'], '', strip_tags(preg_replace('/\s+/', '', $tds[1]->find('p', 1)->innerText()))));
}
// Извлекаем цену из третьего <td>
if (count($tds) >= 3) {
- $itemData['price'] = (float)trim(str_replace(["\u{00A0}", '₽' , ' '], '', strip_tags(preg_replace('/\s+/', ' ', $tds[2]->find('p', 0)->innerText()))));
+ $itemData['price'] = (float)trim(str_replace(["\u{00A0}", '₽', ' '], '', strip_tags(preg_replace('/\s+/', ' ', $tds[2]->find('p', 0)->innerText()))));
}
// Добавляем данные в массив
$orderItems[] = $itemData;
(
preg_replace
(
- '/\s+/',
- ' ',
- $sumBlock->innerText()
+ '/\s+/',
+ ' ',
+ $sumBlock->innerText()
)
)
)
$marketplaceOrder = self::createOrder($orderDetails, $campaignId, $statusId, $substatusId);
if ($marketplaceOrder->save()) {
self::sendMessageToTelegram($marketplaceOrder->guid, "Тестовое сообщение для https://tracker.yandex.ru/ERP-326 из [2]");
- $newOrdersCount += 1;
- self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId, $orderDetails);
- self::saveOrderItems($orderDetails, $marketplaceOrder->id, $marketplaceOrder->warehouse_guid);
+ $newOrdersCount += 1;
+ self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId, $orderDetails);
+ self::saveOrderItems($orderDetails, $marketplaceOrder->id, $marketplaceOrder->warehouse_guid);
} else {
- Yii::error(
- 'Ошибка сохранения заказа: ' . json_encode(
- $marketplaceOrder->getErrors(),
- JSON_UNESCAPED_UNICODE
- )
- );
+ Yii::error(
+ 'Ошибка сохранения заказа: ' . json_encode(
+ $marketplaceOrder->getErrors(),
+ JSON_UNESCAPED_UNICODE
+ )
+ );
}
self::setReadyMarketplaceOrders($marketplaceOrder);
}
} else {
$marketplaceOrder->status_id = $statusId;
$marketplaceOrder->substatus_id = $substatusId;
- if ($index == self::SUBJECT_INDEX[self::SUBJECT_APPROVED] ) {
+ if ($index == self::SUBJECT_INDEX[self::SUBJECT_APPROVED]) {
//заказ принят
if ($marketplaceOrder->raw_data !== json_encode($orderDetails, JSON_UNESCAPED_UNICODE)) {
$marketplaceOrder->raw_data = json_encode($orderDetails, JSON_UNESCAPED_UNICODE);
}
} elseif ($index == self::SUBJECT_INDEX[self::SUBJECT_CHANGED]) {
- $oldRawData = json_decode($marketplaceOrder->raw_data,true, 512, JSON_UNESCAPED_UNICODE);
+ $oldRawData = json_decode($marketplaceOrder->raw_data, true, 512, JSON_UNESCAPED_UNICODE);
$isChanged = false;
// заказ изменен
if (isset($orderDetails['comment']) && (!isset($oldRawData['comment']) || $orderDetails['comment'] != $oldRawData['comment'])) {
(($statusHistoryRecord->status_id !== (int)$statusId && $statusHistoryRecord->status_id !== $deliveredStatusCodeId) ||
($statusHistoryRecord->substatus_id !== (int)$substatusId && $statusHistoryRecord->substatus_id !== $deliveredSubstatusCodeId)) ||
(strtotime($order['date']) > strtotime($statusHistoryRecord->date_from))
- ) {
+ ) {
$statusHistoryRecord->active = 0;
$statusHistoryRecord->date_end = date('Y-m-d H:i:s');
$statusHistoryRecord->save();
}
}
}
-
+
public static function saveOrderItems($order, $orderId, $warehouseGuid)
{
}
}
}
+
public static function extractArticleCode($productName)
{
if (preg_match('/\(([^()]+)\)\s*$/u', $productName, $matches)) {