From 01ec6642902862bfe2721a9c65471972e05f9a11 Mon Sep 17 00:00:00 2001 From: fomichev Date: Tue, 18 Mar 2025 16:08:26 +0300 Subject: [PATCH] =?utf8?q?=D0=9E=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?utf8?q?=D0=B0=20=D0=BF=D0=B8=D1=81=D0=B5=D0=BC=20=D0=BD=D0=BE=D0=B2?= =?utf8?q?=D1=8B=D1=85=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../MarketplaceStoreController.php | 13 +- erp24/media/controllers/FlowwowController.php | 418 ++++++++++++++---- erp24/services/MarketplaceService.php | 40 +- erp24/views/marketplace-store/update.php | 3 +- 4 files changed, 387 insertions(+), 87 deletions(-) diff --git a/erp24/controllers/MarketplaceStoreController.php b/erp24/controllers/MarketplaceStoreController.php index 22448b18..1865876d 100644 --- a/erp24/controllers/MarketplaceStoreController.php +++ b/erp24/controllers/MarketplaceStoreController.php @@ -88,13 +88,24 @@ class MarketplaceStoreController extends Controller if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } + $campaignNameById = []; + + $config = Configuration::getDefaultConfiguration()->setApiKey('Api-Key', Yii::$app->params['YANDEX_MARKET_API_KEY']); + $apiInstance = new Api\CampaignsApi(new GuzzleHttp\Client(), $config); + $campaigns = $apiInstance->getCampaigns(); + /* @var $campaigns Model\GetCampaignsResponse */ + foreach ($campaigns->getCampaigns() as $campaign) { + /* @var $campaign Model\CampaignDTO */ + $campaignNameById[$campaign->getId()] = $campaign->getDomain(); + } return $this->render('update', [ 'model' => $model, 'stores' => $stores, 'storesGuid' => $storesGuid, 'firms' => $firms, - 'warehouses' => $warehouses + 'warehouses' => $warehouses, + 'campaignNameById' => $campaignNameById, ]); } diff --git a/erp24/media/controllers/FlowwowController.php b/erp24/media/controllers/FlowwowController.php index 18c8de1d..de352994 100644 --- a/erp24/media/controllers/FlowwowController.php +++ b/erp24/media/controllers/FlowwowController.php @@ -1,7 +1,9 @@ subject); - $date = mb_decode_mimeheader($overview[0]->date); - $date = date('Y-m-d H:i:s', strtotime($date)); - - if ($subject == 'Новый_оплаченный_заказ') { - if (isset($structure->parts) && count($structure->parts)) { - foreach ($structure->parts as $partNum => $part) { - if ($part->subtype == 'HTML') { - $htmlMessage = imap_fetchbody($inbox, $email_number, $partNum + 1); - $htmlMessage = quoted_printable_decode($htmlMessage); - break; + $date = date('Y-m-d H:i:s', strtotime(mb_decode_mimeheader($overview[0]->date))); + Yii::warning('Тема: ' . json_encode($subject, JSON_UNESCAPED_UNICODE), __METHOD__); + foreach ($subjectPatterns as $pattern) { + if (preg_match($pattern, $subject)) { + Yii::warning('Тема прошла: ' . json_encode($subject, JSON_UNESCAPED_UNICODE), __METHOD__); + if (isset($structure->parts) && count($structure->parts)) { + foreach ($structure->parts as $partNum => $part) { + if ($part->subtype == 'HTML') { + $htmlMessage = imap_fetchbody($inbox, $email_number, $partNum + 1); + $htmlMessage = quoted_printable_decode($htmlMessage); + break; + } } } - } - // Инициализация переменных для избежания undefined - $orderNumber = null; - $items = []; - $totalSum = 0; + $messages[] = [ + 'subject' => $subject, + 'date' => $date, + 'body' => $htmlMessage, + ]; + break; + } + } + // imap_setflag_full($inbox, $email_number, "\\Seen"); + } + } + imap_close($inbox); + if ($messages) { + foreach ($messages as $message) { + $html = $message['body']; + $orderNumber = null; + $items = []; + $totalSum = 0; + if (!empty($html)) { + $html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + $doc = new HtmlDomParser($html); + + $main = $doc->findOneOrFalse("body"); + $body = new SimpleHtmlDom($main->getNode()); + if ($main !== false) { + $orderTitleNode = $main->findOne("h1"); + + if ($orderTitleNode && preg_match('/№(\d+)/', $orderTitleNode->innertext, $matches)) { + $orderNumber = (int)$matches[1]; + } + } + } + if (preg_match($subjectPatterns[0], $message['subject'])) { // Новый заказ + continue; try { - if (!empty($htmlMessage)) { - $htmlMessage = html_entity_decode($htmlMessage, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + // Извлечение товаров + $elements = $main->findOne("p:contains('Детали заказа')")->parentNode(); + if ($elements) { + foreach ($elements->findMultiOrFalse("tr") as $itemRow) { + $img = $itemRow->findOne("td img"); + $nameNode = $itemRow->findOne("td:nth-child(2) p"); + if (!$img || !trim($nameNode->plaintext)) { + continue; + } - $doc = new HtmlDomParser($htmlMessage); + $name = trim($nameNode->plaintext); - $main = $doc->findOneOrFalse("body"); + // Количество + $countNode = $itemRow->findOne("td:nth-child(2) p[style*='#8C8C8C']"); + $countText = $countNode ? $countNode->plaintext : '1'; + $count = (int)filter_var($countText, FILTER_SANITIZE_NUMBER_INT); - if ($main !== false) { - $orderTitleNode = $main->findOne("h1"); + // Сумма + $sumNode = $itemRow->findOne("td:nth-child(3) p"); + $sumText = $sumNode ? $sumNode->plaintext : '0'; + $sum = (float)str_replace([' ', '₽'], '', $sumText); - if ($orderTitleNode && preg_match('/№(\d+)/', $orderTitleNode->innertext, $matches)) { - $orderNumber = (int)$matches[1]; - } + $items[] = ['name' => $name, 'count' => $count, 'sum' => $sum]; + } + } - // Извлечение товаров - $elements = $main->findOne("p:contains('Детали заказа')")->parentNode(); - if ($elements) { - foreach ($elements->findMultiOrFalse("tr") as $itemRow) { - $img = $itemRow->findOne("td img"); - $nameNode = $itemRow->findOne("td:nth-child(2) p"); - if (!$img || !trim($nameNode->plaintext)) continue; + // Общая сумма + $totalSumNodes = $elements->parentNode()->getElementsByTagName('table'); + $totalSumNode = ($totalSumNodes[3])->findOne("tr:contains('Итого оплачено')"); + if ($totalSumNode) { + $totalSum = (float)str_replace([' ', '₽'], + '', + trim(($totalSumNode->findMulti("td"))[1]->plaintext)); + } + } catch (\Exception $e) { + Yii::error( + 'Ошибка: ' . json_encode($e->getMessage(), JSON_UNESCAPED_UNICODE) . " " . $e->getLine( + ) . " " . json_encode($e->getTrace(), JSON_UNESCAPED_UNICODE), + __METHOD__ + ); + } - $name = trim($nameNode->plaintext); + if ($orderNumber !== null) { + $orders[$orderNumber] = [ + 'items' => $items, + 'totalSum' => $totalSum, + 'number' => $orderNumber, + 'date' => $message['date'], - // Количество - $countNode = $itemRow->findOne("td:nth-child(2) p[style*='#8C8C8C']"); - $countText = $countNode ? $countNode->plaintext : '1'; - $count = (int) filter_var($countText, FILTER_SANITIZE_NUMBER_INT); + ]; + } + Yii::warning( + 'HTML Тело письма: ' . json_encode($message['body'], JSON_UNESCAPED_UNICODE), + __METHOD__ + ); + Yii::warning('Новые заказы: ' . json_encode($orders, JSON_UNESCAPED_UNICODE), __METHOD__); + } elseif (preg_match($subjectPatterns[1], $message['subject'])) { + $orderDetails = []; + +// Блок "Доставить" + $deliveryBlock = $main->findOne('p:contains("Доставить")'); + return $main->html(); + if ($deliveryBlock) { + $deliveryBlock = $deliveryBlock->parentNode()->findMulti('p'); + + return json_encode(($deliveryBlock[1])->html(), JSON_UNESCAPED_UNICODE); + $deliveryText = $deliveryBlock->innertext; + Yii::warning('Текст заказа: ' . json_encode($deliveryText, JSON_UNESCAPED_UNICODE), __METHOD__); + $orderDetails['delivery'] = trim($deliveryText); + } - // Сумма - $sumNode = $itemRow->findOne("td:nth-child(3) p"); - $sumText = $sumNode ? $sumNode->plaintext : '0'; - $sum = (float) str_replace([' ', '₽'], '', $sumText); +// Блок "Комментарий" + $commentBlock = $main->findOne('p:contains("Комментарий")'); + if ($commentBlock) { + $commentBlock = $commentBlock->nextSibling(); + $orderDetails['comment'] = trim($commentBlock->innerText()); + } - $items[] = ['name' => $name, 'count' => $count, 'sum' => $sum]; - } - } +// Блок "Клиент" (Отправитель) + $clientBlock = $main->findOne('p:contains("Клиент")'); + if ($clientBlock) { + $clientBlock = $clientBlock->nextSibling(); + $clientText = trim($clientBlock->innerText()); + $orderDetails['sender'] = $clientText; + } - // Общая сумма - $totalSumNodes = $elements->parentNode()->getElementsByTagName('table'); - $totalSumNode = ($totalSumNodes[3])->findOne("tr:contains('Итого оплачено')"); - if ($totalSumNode) { - $totalSum = (float) str_replace([' ', '₽'], '', trim(($totalSumNode->findMulti("td"))[1]->plaintext)); - } + + // Извлечение товаров + + + Yii::warning( + 'HTML Тело письма: ' . json_encode($message['body'], JSON_UNESCAPED_UNICODE), + __METHOD__ + ); + + $orderItems = []; + +// Ищем все комментарии + $startComments = $main->find('comment:contains("START ITEM")'); + + foreach ($startComments as $startComment) { + $itemData = [ + 'image' => '', + 'name' => '', + 'count' => '', + 'price' => '', + ]; + + // Находим следующий элемент после комментария + $tr = $startComment->nextSibling(); + if ($tr && $tr->tag === 'tr') { + // Извлекаем изображение + $img = $tr->find('img')[0]; + if ($img) { + $itemData['image'] = $img->src; + } + + // Извлекаем название и количество из второго + $tds = $tr->find('td'); + if (count($tds) >= 2) { + $itemData['name'] = trim($tds[1]->find('p')[0]->innerText()); + $itemData['count'] = trim($tds[1]->find('p')[1]->innerText()); + } + + // Извлекаем цену из третьего + if (count($tds) >= 3) { + $itemData['price'] = trim($tds[2]->find('p')[0]->innerText()); } } - } catch (\Exception $e) { - Yii::error('Ошибка: ' . json_encode($e->getMessage(), JSON_UNESCAPED_UNICODE) . " " . $e->getLine() . " " . json_encode($e->getTrace(), JSON_UNESCAPED_UNICODE), __METHOD__); + + // Добавляем данные в массив + $orderItems[] = $itemData; } - if ($orderNumber !== null) { - $orders[] = [ - $orderNumber => [ - 'items' => $items, - 'totalSum' => $totalSum, - 'number' => $orderNumber, - 'date' => $date, - ] - ]; + $orderDetails['items'] = $orderItems; + // Общая сумма + $total = ''; + +// Ищем комментарий + $startTotalComment = $main->findOne('comment:contains("START TOTAL")'); + if ($startTotalComment) { + // Находим следующий элемент после комментария + $tr = $startTotalComment->nextSibling(); + if ($tr && $tr->tag === 'tr') { + // Извлекаем текст из второго + $tds = $tr->find('td'); + if (count($tds) >= 2) { + $totalSum = trim($tds[1]->find('p')[0]->innerText()); + } + } } + $orderDetails['totalSum'] = $totalSum; + $orders[$orderNumber] = $orderDetails; - Yii::warning('HTML Тело письма: ' . json_encode($orders, JSON_UNESCAPED_UNICODE), __METHOD__); - break; + Yii::warning('Принятые заказы: ' . json_encode($orders, JSON_UNESCAPED_UNICODE), __METHOD__); } - - // imap_setflag_full($inbox, $email_number, "\\Seen"); + // Yii::warning('HTML Тело письма: ' . json_encode($message['body'], JSON_UNESCAPED_UNICODE), __METHOD__); } } else { Yii::warning('Новых сообщений не обнаружено.', __METHOD__); } - imap_close($inbox); + return ['success' => true, 'count' => $count]; } + + public function actionParseMail() + { + set_time_limit(300); + Yii::$app->response->format = Response::FORMAT_JSON; + + $html = file_get_contents('./runtime/file.html'); + + if (!empty($html)) { + $html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + $doc = new HtmlDomParser($html); + + $main = $doc->findOneOrFalse("body"); + + if ($main !== false) { + $orderTitleNode = $main->findOne("h1"); + + if ($orderTitleNode && preg_match('/№(\d+)/', $orderTitleNode->innertext, $matches)) { + $orderNumber = (int)$matches[1]; + } + } + $orderDetails['number'] = $orderNumber; + $deliveryText = ''; + $commentText = ''; + $clientText = ''; + $recipientText = ''; + $orderItems = []; + + + $deliveryBlock = $main->findOne('p:contains("Доставить")'); + $pickupBlock = $main->findOne('p:contains("Самовывоз")'); + + if ($deliveryBlock && $deliveryBlock->nextNonWhitespaceSibling()) { + $deliveryBlock = $deliveryBlock->nextNonWhitespaceSibling(); + $deliveryText = "Доставка: " . strip_tags($deliveryBlock->innerText()); + $deliveryText = preg_replace('/\s+/', ' ', $deliveryText); + } elseif ($pickupBlock && $pickupBlock->nextNonWhitespaceSibling()) { + $pickupBlock = $pickupBlock->nextNonWhitespaceSibling(); + $deliveryText = "Самовывоз: " . strip_tags($pickupBlock->innerText()); + $deliveryText = preg_replace('/\s+/', ' ', $deliveryText); + } + + if ($deliveryText) { + Yii::warning('Текст заказа: ' . $deliveryText, __METHOD__); + $orderDetails['delivery'] = trim($deliveryText); + } + + $commentBlock = $main->findOne('p:contains("Комментарий")'); + if ($commentBlock && $commentBlock->nextNonWhitespaceSibling()) { + $commentBlock = $commentBlock->nextNonWhitespaceSibling(); + $commentText = preg_replace('/\s+/', ' ', $commentBlock->innerText()); + $orderDetails['comment'] = trim($commentText); + } + + + + $clientBlock = $main->findOne('p:contains("Клиент")'); + $senderBlock = $main->findOne('p:contains("Отправитель")'); + + if ($clientBlock && $clientBlock->nextNonWhitespaceSibling()) { + $clientBlock = $clientBlock->nextNonWhitespaceSibling(); + $clientText = "Клиент: " . strip_tags($clientBlock->innerText()); + $phoneLink = $clientBlock->find('a', 0); + if ($phoneLink) { + $clientText .= ' ' . preg_replace('/tel:/', ' ', $phoneLink->getAttribute('href')); + } + } elseif ($senderBlock && $senderBlock->nextNonWhitespaceSibling()) { + $senderBlock = $senderBlock->nextNonWhitespaceSibling(); + $clientText = "Отправитель: " . strip_tags($senderBlock->innerText()); + $phoneLink = $senderBlock->find('a', 0); + if ($phoneLink) { + $clientText .= ' ' . preg_replace('/tel:/', ' ', $phoneLink->getAttribute('href')); + } + } + + if ($clientText) { + $orderDetails['client'] = str_replace('Позвонить', '', $clientText); + } + + $recipientBlock = $main->findOne('p:contains("Получатель")'); + if ($recipientBlock && $recipientBlock->nextNonWhitespaceSibling()) { + $recipientBlock = $recipientBlock->nextNonWhitespaceSibling(); + $recipientText = strip_tags( + str_replace('Позвонить', '', $recipientBlock->innerText()) + ) . ' ' . preg_replace('/tel:/', ' ', $recipientBlock->find('a', 0)->getAttribute('href')); + $orderDetails['recipient'] = $recipientText; + } + + + $itemsBlock = $main->findOneOrFalse('h2:contains("Детали заказа")') ? $main->findOne('h2:contains("Детали заказа")') : $main->findOne('p:contains("Детали заказа")'); + $itemsTable = $itemsBlock->parentNode()->find('table', 2); + + $itemsRows = $itemsTable->find('tr'); + foreach ($itemsRows as $itemsRow) { + Yii::warning('Строка заказа: ' . json_encode($itemsRow->innerText(), JSON_UNESCAPED_UNICODE), __METHOD__); + $itemData = [ + 'name' => '', + 'count' => '', + 'price' => '', + ]; + + + // Извлекаем название и количество из второго + $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['count'] = trim(str_replace(["\u{00A0}", 'шт.'], '', strip_tags(preg_replace('/\s+/', '', $tds[1]->find('p', 1)->innerText())))); + } + + // Извлекаем цену из третьего + if (count($tds) >= 3) { + $itemData['price'] = (float)trim(str_replace(["\u{00A0}", '₽' , ' '], '', strip_tags(preg_replace('/\s+/', ' ', $tds[2]->find('p', 0)->innerText())))); + } + + + // Добавляем данные в массив + $orderItems[] = $itemData; + } + $totalSum = 0; + $sumBlock = $itemsBlock->parentNode()->find('table', 3); + $sumRow = $sumBlock->find('tr'); + + $sumTds = $sumRow->find('td'); + if (count($sumTds) >= 2) { + $totalSum = (float)trim(str_replace(["\u{00A0}", '₽' , ' '], '', strip_tags(preg_replace('/\s+/', ' ', $sumTds[1]->innerText())))); + + } + $orderDetails['items'] = $orderItems; + $orderDetails['totalSum'] = $totalSum; + } + $order[$orderNumber] = $orderDetails; + return [ + 'success' => true, + 'order' => $order + + ]; + } + } diff --git a/erp24/services/MarketplaceService.php b/erp24/services/MarketplaceService.php index 92ac6d84..186b349e 100644 --- a/erp24/services/MarketplaceService.php +++ b/erp24/services/MarketplaceService.php @@ -1405,12 +1405,12 @@ class MarketplaceService $countText = $countNode ? $countNode->plaintext : '1'; $count = (int) filter_var($countText, FILTER_SANITIZE_NUMBER_INT); - // Сумма - $sumNode = $itemRow->findOne("td:nth-child(3) p"); - $sumText = $sumNode ? $sumNode->plaintext : '0'; - $sum = (float) str_replace([' ', '₽'], '', $sumText); + // Цена + $priceNode = $itemRow->findOne("td:nth-child(3) p"); + $priceText = $priceNode ? $priceNode->plaintext : '0'; + $price = (float) str_replace([' ', '₽'], '', $priceText); - $items[] = ['name' => $name, 'count' => $count, 'sum' => $sum]; + $items[] = ['name' => $name, 'count' => $count, 'price' => $price]; } } @@ -1436,7 +1436,7 @@ class MarketplaceService } Yii::warning('HTML Тело письма: ' . json_encode($orders, JSON_UNESCAPED_UNICODE), __METHOD__); - break; + } // imap_setflag_full($inbox, $email_number, "\\Seen"); @@ -1477,9 +1477,9 @@ class MarketplaceService $marketplaceOrder = self::createOrder($order, $campaignId, $statusId, $substatusId); if ($marketplaceOrder->save()) { - $newOrdersCount++; + $newOrdersCount += 1; self::createStatusHistory($marketplaceOrder->id, $statusId, $substatusId); - self::saveOrderItems($order, $marketplaceOrder->id); + self::saveOrderItems($order, $marketplaceOrder->id, $marketplaceOrder->warehouse_guid); } else { Yii::error( @@ -1514,6 +1514,9 @@ class MarketplaceService private static function createOrder($order, $campaignId, $statusId, $substatusId) { + $store = MarketplaceStore::find() + ->where(['warehouse_guid' => (string)$campaignId]) + ->andWhere(['warehouse_id' => 1])->one(); $marketplaceOrder = new MarketplaceOrders(); $marketplaceOrder->marketplace_order_id = (string)$order['number']; $marketplaceOrder->creation_date = date('Y-m-d H:i:s', strtotime($order['date'])); @@ -1533,7 +1536,7 @@ class MarketplaceService $marketplaceOrder->fake = 0; $marketplaceOrder->marketplace_name = 'ФлауВау'; $marketplaceOrder->marketplace_id = 1; - + $marketplaceOrder->store_id = $store->store_id; return $marketplaceOrder; } @@ -1550,7 +1553,7 @@ class MarketplaceService $history->date_end = '2100-01-01 00:00:00'; $history->save(); } - private static function saveOrderItems($order, $orderId) + private static function saveOrderItems($order, $orderId, $warehouseGuid) { $items = $order['items']; if (!$items) { @@ -1560,10 +1563,25 @@ class MarketplaceService $orderItem = new MarketplaceOrderItems(); $orderItem->order_id = $orderId; $orderItem->external_item_id = $order['number']; + $orderItem->offer_name = $item['name']; $orderItem->offer_id = $item['name']; $orderItem->price = $item['price']; $orderItem->count = $item['count']; - $orderItem->save(); + $orderItem->buyer_price = $item['price']; + $orderItem->buyer_price_before_discount = $item['price']; + $orderItem->price_before_discount = $item['price']; + $orderItem->vat = "UNKNOWN"; + $orderItem->shop_sku = $item['name']; + $orderItem->subsidy = 0; + $orderItem->partner_warehouse_id = $warehouseGuid; + $orderItem->promos = null; + $orderItem->subsidies = null; + if (!$orderItem->save()) { + Yii::error( + 'Ошибка сохранения элеиента: ' . json_encode($orderItem->getErrors(), JSON_UNESCAPED_UNICODE) + ); + } + } } diff --git a/erp24/views/marketplace-store/update.php b/erp24/views/marketplace-store/update.php index 63bee730..d0d84c14 100644 --- a/erp24/views/marketplace-store/update.php +++ b/erp24/views/marketplace-store/update.php @@ -16,7 +16,8 @@ $this->params['breadcrumbs'][] = $this->title; 'stores' => $stores, 'storesGuid' => $storesGuid, 'firms' => $firms, - 'warehouses' => $warehouses + 'warehouses' => $warehouses, + 'campaignNameById' => $campaignNameById, ]) ?> -- 2.39.5