From 14cc4efbfef8dd4910884911c0a9c0670fdbaa8d Mon Sep 17 00:00:00 2001 From: fomichev Date: Thu, 20 Mar 2025 16:09:11 +0300 Subject: [PATCH] =?utf8?q?=D0=A1=D0=B1=D0=BE=D1=80=20=D1=81=D0=BF=D0=B8?= =?utf8?q?=D1=81=D0=B5=D0=BC=20=D0=B8=D0=B7=20=D0=BF=D0=B0=D0=BF=D0=BE?= =?utf8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- erp24/commands/MarketplaceController.php | 49 ++++- erp24/media/controllers/FlowwowController.php | 26 ++- erp24/services/MarketplaceService.php | 168 ++++++++++++------ 3 files changed, 178 insertions(+), 65 deletions(-) diff --git a/erp24/commands/MarketplaceController.php b/erp24/commands/MarketplaceController.php index 56c90b7e..cc145bd7 100644 --- a/erp24/commands/MarketplaceController.php +++ b/erp24/commands/MarketplaceController.php @@ -21,6 +21,23 @@ use yii_app\services\WhatsAppService; class MarketplaceController extends Controller { + /** + * @var string|null дата в формате 2025-01-01 + */ + public $date; + /** + * @var int|null передаем 1 (true), чтобы забирать начиная с даты + */ + public $since; + /** + * @var int|null передаем 1 (true), чтобы забирать со старого ящика Zakaz-bazacvetov24@yandex.ru + */ + public $oldMail; + /** + * @var int|null передаем 0 (false), чтобы забирать все письма а не только непросмотренные UNSEEN + */ + public $seen; + public function actionYandex() { $infoForMarketplace = MarketplaceService::infoForMarketplace(2); @@ -73,17 +90,43 @@ class MarketplaceController extends Controller public function actionGetFlowwowOrders() { - $messages = MarketplaceService::getFlowwowOrdersFromMail(); - Yii::warning("Заказы " . json_encode($messages, JSON_UNESCAPED_UNICODE)); + $date = $this->date ?? null; + $since = (bool)($this->since ?? 0); + $oldMail = (bool)($this->oldMail ?? 0); + $seen = (bool)($this->seen ?? 0); + + $countMessages = 0; + $count = 0; + $this->stdout( + "Удалось сохранить {$date} новых заказов из {$this->date} сообщений почты.\n", + BaseConsole::FG_GREEN + ); + $progressCallback = function ($message) { + $this->stdout($message . "\n", BaseConsole::FG_YELLOW); + }; + $messages = MarketplaceService::getFlowwowOrdersFromMail($date, $since, $oldMail, $progressCallback, $seen); + + $countMessages = count($messages); $count = MarketplaceService::processMessages($messages); $this->stdout( - "Удалось сохранить {$count} новых заказов из почты.\n", + "Удалось сохранить {$count} новых заказов из {$countMessages} сообщений почты.\n", BaseConsole::FG_GREEN ); return ExitCode::OK; } + public function options($actionID) + { + $options = parent::options($actionID); + $options[] = 'date'; + $options[] = 'since'; + $options[] = 'oldMail'; + $options[] = 'seen'; + + return $options; + } + } \ No newline at end of file diff --git a/erp24/media/controllers/FlowwowController.php b/erp24/media/controllers/FlowwowController.php index 1f26ee4e..a7212b5c 100644 --- a/erp24/media/controllers/FlowwowController.php +++ b/erp24/media/controllers/FlowwowController.php @@ -56,14 +56,32 @@ class FlowwowController extends Controller { set_time_limit(300); Yii::$app->response->format = Response::FORMAT_JSON; - $hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; + // $hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; $username = 'flow@bazacvetov24.ru'; $password = 'ctqamxqeshgxwsgn'; - $hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; - $username = 'Zakaz-bazacvetov24@yandex.ru'; - $password = 'jyxnwwwvgpwhzbdu'; + // $hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; + // $username = 'Zakaz-bazacvetov24@yandex.ru'; + // $password = 'jyxnwwwvgpwhzbdu'; + $mailbox = '{imap.yandex.ru:993/imap/ssl}'; + $inbox = imap_open($mailbox . 'INBOX', $username, $password); + $folders = imap_list($inbox, $mailbox, '*'); // Получение всех папок + imap_close($inbox); + $count = 0; + foreach ($folders as $folder) { + $inbox = imap_open($folder, $username, $password); + if (!$inbox) { + Yii::error('Ошибка подключения: ' . imap_last_error(), __METHOD__); + } + + + $emails = imap_search($inbox,'SINCE "20-Mar-2025" FROM "" SEEN'); + + $count += $emails ? count($emails) : 0; + imap_close($inbox); + } + return $count; // Устанавливаем таймауты IMAP imap_timeout(IMAP_OPENTIMEOUT, 120); imap_timeout(IMAP_READTIMEOUT, 120); diff --git a/erp24/services/MarketplaceService.php b/erp24/services/MarketplaceService.php index aededd7b..8535f5fb 100644 --- a/erp24/services/MarketplaceService.php +++ b/erp24/services/MarketplaceService.php @@ -1341,35 +1341,28 @@ class MarketplaceService } } - public static function getFlowwowOrdersFromMail() + public static function getFlowwowOrdersFromMail($date = null, $useSince = false, $useAlternateMailbox = false, $progressCallback = null, $seen = false) { set_time_limit(300); - - $hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; - $username = 'Zakaz-bazacvetov24@yandex.ru'; - $password = 'jyxnwwwvgpwhzbdu'; - - /*$hostname = '{imap.yandex.ru:993/imap/ssl}INBOX'; - $username = 'flow@bazacvetov24.ru'; - $password = 'ctqamxqeshgxwsgn';*/ - // Устанавливаем таймауты IMAP imap_timeout(IMAP_OPENTIMEOUT, 120); imap_timeout(IMAP_READTIMEOUT, 120); imap_timeout(IMAP_WRITETIMEOUT, 120); imap_timeout(IMAP_CLOSETIMEOUT, 120); - $inbox = imap_open($hostname, $username, $password); - if (!$inbox) { - Yii::error('Ошибка подключения: ' . imap_last_error(), __METHOD__); - return ['success' => false]; + $searchCriteria = ''; + $searchCriteria .= ($useSince ? 'SINCE ' : 'ON '); + + + if (!$date) { + $date = date('d-M-Y'); + $searchCriteria .= '"' . $date . '" '; + } else { + $date = date('d-M-Y', strtotime($date)); + $searchCriteria .= '"' . $date . '" '; } - //$inboxInfo = imap_mailboxmsginfo($inbox); - //Yii::warning(' Состояние ящика: ' . print_r($inboxInfo, true), __METHOD__); - $emails = imap_search($inbox, 'ON "14-Feb-2025" FROM "info@flowwow.com" '); - //$emails = imap_search($inbox, 'ON "18-Mar-2025" FROM "info@flowwow.com" '); - $messages = []; + $searchCriteria .= ($seen ? 'SEEN ' : 'UNSEEN '); $subjectPatterns = [ self::SUBJECT_NEW, @@ -1379,42 +1372,91 @@ class MarketplaceService self::SUBJECT_DELIVERED, ]; - if ($emails) { - foreach ($emails as $email_number) { - $overview = imap_fetch_overview($inbox, $email_number, 0); - $structure = imap_fetchstructure($inbox, $email_number); - $htmlMessage = ''; - $subject = mb_decode_mimeheader($overview[0]->subject); - $from = mb_decode_mimeheader($overview[0]->from); - $to = mb_decode_mimeheader($overview[0]->to); - $date = date('Y-m-d H:i:s', strtotime(mb_decode_mimeheader($overview[0]->date))); - foreach ($subjectPatterns as $pattern) { - if (preg_match($pattern, $subject)) { - $subjectIndex = self::SUBJECT_INDEX[$pattern]; - 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; + $hostname = '{imap.yandex.ru:993/imap/ssl}'; + if ($useAlternateMailbox) { + $username = 'Zakaz-bazacvetov24@yandex.ru'; + $password = 'jyxnwwwvgpwhzbdu'; + $searchCriteria .= 'FROM ""'; + } else { + $username = 'flow@bazacvetov24.ru'; + $password = 'ctqamxqeshgxwsgn'; + $searchCriteria .= 'FROM ""'; + } + + if ($progressCallback) { + call_user_func($progressCallback, "Строка поиска: {$searchCriteria}"); + } + + if ($progressCallback) { + call_user_func($progressCallback, "Подключение к почтовому ящику..."); + } + $inbox = imap_open($hostname . 'INBOX', $username, $password); + if (!$inbox) { + Yii::error('Ошибка подключения: ' . imap_last_error(), __METHOD__); + } + if ($progressCallback) { + call_user_func($progressCallback, "Получение списка папок..."); + } + $folders = imap_list($inbox, $hostname, '*'); + imap_close($inbox); + + $messages = []; + + foreach ($folders as $folder) { + $inbox = imap_open($folder, $username, $password); + if (!$inbox) { + Yii::error('Ошибка подключения: ' . imap_last_error(), __METHOD__); + } + if ($progressCallback) { + call_user_func($progressCallback, "Поиск писем в папке: $folder..."); + } + + $emails = imap_search($inbox, $searchCriteria); + + if ($emails) { + if ($progressCallback) { + call_user_func($progressCallback, "Найдено " . count($emails) . " писем."); + } + foreach ($emails as $index => $email_number) { + $overview = imap_fetch_overview($inbox, $email_number, 0); + $structure = imap_fetchstructure($inbox, $email_number); + $htmlMessage = ''; + $subject = mb_decode_mimeheader($overview[0]->subject); + $from = mb_decode_mimeheader($overview[0]->from); + $to = mb_decode_mimeheader($overview[0]->to); + $date = date('Y-m-d H:i:s', strtotime(mb_decode_mimeheader($overview[0]->date))); + foreach ($subjectPatterns as $pattern) { + if (preg_match($pattern, $subject)) { + $subjectIndex = self::SUBJECT_INDEX[$pattern]; + 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); + break; + } } } - } - $messages[] = [ - 'subject' => $subject, - 'subject_index' => $subjectIndex, - 'from' => $from, - 'to' => $to, - 'date' => $date, - 'body' => $htmlMessage, - ]; + $messages[] = [ + 'subject' => $subject, + 'subject_index' => $subjectIndex, + 'from' => $from, + 'to' => $to, + 'date' => $date, + 'body' => $htmlMessage, + ]; + } + } + imap_setflag_full($inbox, $email_number, "\\Seen"); + if ($progressCallback) { + call_user_func($progressCallback, "От: " . $from . " тема " . $subject . " от " . $date); + call_user_func($progressCallback, "Обработано писем: " . ($index + 1) . " из " . count($emails)); } } - // imap_setflag_full($inbox, $email_number, "\\Seen"); } + imap_close($inbox); } - imap_close($inbox); + usort($messages, fn($a, $b) => $a['subject_index'] <=> $b['subject_index']); return $messages; } @@ -1487,6 +1529,13 @@ class MarketplaceService $clientText = ''; $recipientText = ''; $orderItems = []; + $orderLink = ''; + + $linkBlock = $main->findOneOrFalse('a:contains("Перейти в заказ ")'); + if ($linkBlock) { + $link = $linkBlock->getAttribute('href'); + $orderDetails['orderLink'] = $link; + } $deliveryBlock = $main->findOne('p:contains("Доставить")'); @@ -1549,10 +1598,10 @@ class MarketplaceService $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) { @@ -1631,7 +1680,7 @@ class MarketplaceService $marketplaceOrder = self::createOrder($orderDetails, $campaignId, $statusId, $substatusId); if ($marketplaceOrder->save()) { $newOrdersCount += 1; - self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId); + self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId, $orderDetails); self::saveOrderItems($orderDetails, $marketplaceOrder->id, $marketplaceOrder->warehouse_guid); } else { Yii::error( @@ -1643,15 +1692,16 @@ class MarketplaceService } } } else { - if ($index == self::SUBJECT_APPROVED || $index == self::SUBJECT_CHANGED) { + if ($index == self::SUBJECT_INDEX[self::SUBJECT_APPROVED] || $index == self::SUBJECT_INDEX[self::SUBJECT_CHANGED]) { //заказ принят или изменен $marketplaceOrder->status_id = $statusId; $marketplaceOrder->substatus_id = $substatusId; + if ($marketplaceOrder->raw_data !== json_encode($orderDetails, JSON_UNESCAPED_UNICODE)) { $marketplaceOrder->raw_data = json_encode($orderDetails, JSON_UNESCAPED_UNICODE); } if ($marketplaceOrder->save()) { - self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId); + self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId, $orderDetails); } else { Yii::error('Не удалось обновить заказ' . json_encode($marketplaceOrder->getErrors(), JSON_UNESCAPED_UNICODE)); } @@ -1660,7 +1710,7 @@ class MarketplaceService $marketplaceOrder->status_id = $statusId; $marketplaceOrder->substatus_id = $substatusId; if ($marketplaceOrder->save()) { - self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId); + self::createOrUpdateStatusHistory($marketplaceOrder->id, $statusId, $substatusId, $orderDetails); } else { Yii::error('Не удалось обновить заказ' . json_encode($marketplaceOrder->getErrors(), JSON_UNESCAPED_UNICODE)); } @@ -1717,13 +1767,15 @@ class MarketplaceService return $marketplaceOrder; } - private static function createOrUpdateStatusHistory($orderId, $statusId, $substatusId) + private static function createOrUpdateStatusHistory($orderId, $statusId, $substatusId, $order) { $statusHistoryRecord = MarketplaceOrderStatusHistory::find()->where(['order_id' => $orderId])->andWhere(['active' => 1])->one(); if ( $statusHistoryRecord && ($statusHistoryRecord->status_id !== (int)$statusId || - $statusHistoryRecord->substatus_id !== (int)$substatusId) + $statusHistoryRecord->substatus_id !== (int)$substatusId || + $order['date'] !== $statusHistoryRecord->date_from + ) ) { $statusHistoryRecord->active = 0; $statusHistoryRecord->date_end = date('Y-m-d H:i:s'); @@ -1735,7 +1787,7 @@ class MarketplaceService $newStatusHistoryRecord->substatus_id = (int)$substatusId; $newStatusHistoryRecord->active = 1; $newStatusHistoryRecord->initiator = "ERP"; - $newStatusHistoryRecord->date_from = date('Y-m-d H:i:s'); + $newStatusHistoryRecord->date_from = date('Y-m-d H:i:s', strtotime($order['date'])); $newStatusHistoryRecord->date_end = date('Y-m-d H:i:s', strtotime("2100-01-01")); if (!$newStatusHistoryRecord->save()) { Yii::error( @@ -1752,7 +1804,7 @@ class MarketplaceService $history->substatus_id = $substatusId; $history->active = 1; $history->initiator = "ERP"; - $history->date_from = date('Y-m-d H:i:s'); + $history->date_from = date('Y-m-d H:i:s', strtotime($order['date'])); $history->date_end = '2100-01-01 00:00:00'; if (!$history->save()) { -- 2.39.5