Как автоматически менять цены на сайте без загрузки и выгрузки Excel файла с прайсом
30 March, 15:56
398
0
|
Сегодня на связи отдел разработки и поддержки сайтов Зекслер. Продолжаем рассказывать, как автоматизируем бизнес процессы клиентов (писали как автоматизировали создание коммерческих предложений в Битрикс 24), и в этот раз сделали синхронизацию цен из Google-таблицы (дабы не грузить Excel и прочее) и цен на сайте производителя гаражей и хозблоков SKOGGY (да, для многих производственников делаем полный цикл по маркетингу, продажам, автоматизации и управленческому учету). В статье будут строчки кода и прочая внутрянка, но донесению сути она не должна помешать. А если всё же помешала, пиши в комментариях, учтём в следующих материалах. Подписывайтесь на наш Телеграм-канал, где мы ежедневно публикуем посты по теме не только разработки, но и дизайна, маркетинга, продвижения и т.д. Будем рады новым подписчикам! Возвращаемся к модулю. Задача состояла в разработке модуля для CMS Drupal, который синхронизирует данные из гугл документа формата Excel (Google Spreadsheet) в колонке с ценами в поля для цен на сайте. СОДЕРЖАНИЕ 1. Подготовка колонки с артикулами в Google таблице 2. Создание приложения в Google консоли 3. Получение токена для ClientApi Google 4. Возможные проблемы получения токена 5. Завершение настройки модуля 6. Как это работает для менеджера Подготовка колонки с артикулами в Google таблицеПредварительно необходимо было задать связь записи продукта и таблицы. Для это в файле документа организовали колонку с уникальными полями (Артикулы), отвечающими за связь этой строки (продукта) с вариантом продукта в Drupal. В нашем случае, это колонка C. Колонка с ценами – это N. Начальная строка 5, а конечная 105. После добавления всех артикулов в таблицу и правильных цен, переходим к следующему этапу. Создание приложения в Google консолиСледующий шаг – создание приложения. Переходим в Google Cloud Console и создаем отдельное приложение. Подключаем к нему (ENABLE APIS AND SERVICES) Google Drive API. Далее нужно получить доступ к приложению. Для этого переходим в credentials и нажимаем Create credentials. После заполнения и добавления тестового пользователя, нужно скачать Client secrets в формате json (справа в строке). После этого необходимо дать разрешения для доменов Authorized JavaScript origins и Authorized redirect URIs. В нашем случае это localhost и localhost/state. Сохраненный файл json нужен для получения токена, который будем получать с помощью php-файла в отдельном скрипте в консоле. Получение токена для ClientApi GoogleТеперь нужно организовать получение токена. Для этого создаем в папке микропроекта composer.json и добавим туда google/apiclient посредством команды: composer require google/apiclient Делаем файл php с подгрузкой require __DIR__ . '/vendor/autoload.php'; А скачанный файл credentials размещаем в той же папке composer.json { "name": "my/google_spreadsheet_api", "type": "my-api", "description": "Library for google api", "require": { "google/apiclient": "^2.0" }, "minimum-stability": "dev" } Файл index.php:
require __DIR__ .'/vendor/autoload.php'; if (php_sapi_name() != 'cli') { throw new Exception('This application must be run on the command line.'); } $pre_dir = __DIR__ . '/'; $relocation_url = 'http://localhost/state'; $path_to_credentials = $pre_dir.'credentials.json'; $path_to_result_token = $pre_dir. 'token.json'; use Google\Client; /** * Returns an authorized API client. * @return Client the authorized client object */ function getClient() { global $relocation_url, $path_to_credentials, $path_to_result_token; $client = new Google\Client(); $client->setApplicationName('Google Sheets API PHP Quickstart'); $client->setScopes('https://www.googleapis.com/auth/spreadsheets'); $client->setAuthConfig($path_to_credentials); $client->setAccessType('offline'); $client->setPrompt('select_account consent'); $client->setRedirectUri($relocation_url); // Load previously authorized token from a file, if it exists. // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. $tokenPath = $path_to_result_token; if (file_exists($tokenPath)) { $accessToken = json_decode(file_get_contents($tokenPath), true); $client->setAccessToken($accessToken); } // If there is no previous token or it's expired. if ($client->isAccessTokenExpired()) { // Refresh the token if possible, else fetch a new one. if ($client->getRefreshToken()) { $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); } else { // Request authorization from the user. $authUrl = $client->createAuthUrl(); printf("Open the following link in your browser:\n%s\n", $authUrl); print 'Enter verification code: '; $authCode = trim(fgets(STDIN)); // Exchange authorization code for an access token. $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAccessToken($accessToken); // Check to see if there was an error. if (array_key_exists('error', $accessToken)) { throw new Exception(join(', ', $accessToken)); } } // Save the token to a file. if (!file_exists(dirname($tokenPath))) { mkdir(dirname($tokenPath), 0700, true); } file_put_contents($tokenPath, json_encode($client->getAccessToken())); } return $client; } // Get the API client and construct the service object. $client = getClient(); Показываем пример файла credentials.json {"web":{"client_id":"...","project_id":"gpru-artdetox-driven-bulwark","auth_uri": com/oauth2/v1/certs","client_secret":"...","redirect_uris":["http://localhost/state"],"javascript_origins": ["http://localhost"]}} Скрипт в index.php выполняется только в консоли php index.php В результате выполнения скрипта в терминале (консоли) получим примерно следующее: Копируем полученную ссылку и вводим в строку браузера. Сейчас нужно получить код авторизации для того адреса email, который будет работать с этим приложением. После авторизации и получения доступа к приложению, к вашим файлам Excel будет перенаправление примерно по такой ссылке: http://localhost/state?code=4/0AWyig&scope=https://www.googleapis.com/auth/spreadsheets Копируем code и вставляем в терминал. После этого получим файл token.json. Возможные проблемы получения токенаПри получении токена могут возникнуть ошибки. Рассмотрим наиболее частые из них. Проблема 1: Нет доступа к приложению или приложение не проверялось. Решение: Добавьте тестового пользователя в разделе OAuth consent screen. Проблема 2: Fatal error: Uncaught InvalidArgumentException: Redirect URI must be absolute in /var/www/vendor/google/auth/src/OAuth2.php:793 Решение: Эта ошибка связана с тем, что в разделе credentials (https://console.cloud.google.com/apis/credentials) проекта не указаны Authorized JavaScript origins и Authorized redirect URIs. Необходимо их заполнить и сохранить. При этом сохранение будет происходит в течение 5 минут. Завершение настройки модуляПосле проведения всех манипуляций, организация получения данных и отправление их на обработку в Batch-процесс выглядит так. Важно! Файл с которым работаете должен быть доступен для тестового пользователя, либо должен быть открыт доступ по ссылке (чтение). К примеру, SheetId с файла https://docs.google.com/spreadsheets/d/3xS34U5аZ8zVzU65ho-VFRVg/edit#gid=0 – это «3xS34U5аZ8zVzU65ho-VFRVg». use Drupal\mw_google_spreadsheet\GetClient; use Google\Service\Sheets; /* Это колонка - например E. Колонка с ценами - например N Начальная строка 5, а конечная 105. */ /* Получаем доступ к гугл файлу */ $columnArticul = 'E'; $columnPrice = 'N'; $start = 5; $end = 105; /* Ид рабочей области - файла гугл, берётся со ссылки на файл. */ $spreadsheetId = '1xS34U5vZ8z5jyblSJOvLUUShINhgKEVzU35ho-VFRVg'; $client = new GetClient(); $cl = $client->get(); $service = new Sheets($cl); $range = $columnArticul . $start . ':' . $columnPrice . $end; try { $response = $service->spreadsheets_values->get($spreadsheetId, $range); $values = $response->getValues(); }catch (Exception $e){ \Drupal::messenger()->addMessage( 'Выброшено исключение: ', $e->getMessage(), "\n die(); } $num_operations = count($values); $this->messenger()->addMessage($this->t('Creating an array of @num operations', ['@num' => $num_operations])); $operations = []; $i = 1; foreach ($values as $value){ $operations[] = [ 'mw_google_spreadsheet_op_1', [ $value, $this->t('(Operation @operation)', ['@operation' => $i]), ], ]; $i++; } $batch = [ 'title' => $this->t('Creating an array of @num operations', ['@num' => $num_operations]), 'operations' => $operations, 'finished' => 'mw_google_spreadsheet_finished', ]; return $batch; Функция обработки каждой строки 'mw_google_spreadsheet_op_1' в Batch-процессе выглядит так (описание в комментариях): /** * Batch operation for batch 1: one at a time. * * This is the function that is called on each operation in batch 1. */ function mw_google_spreadsheet_op_1($rowFromExcel, $operation_details, &$context) { /* Пример полученной строки из файла 0 => "КХС-03-П-Т-Б" 1 => "Контейнер" 2 => "Стандарт" 3 => "3,06м" 4 => "2,16" 5 => "2,06" 6 => "200" 7 => "Торцевая" 8 => "Плоская" 9 => "Пол OSB" 10 => "Цинк" 11 => "р.106 800" */ //название поля из настройки сущности вариантов продукта - field_excele_artikul /* получение всех записей вариантов для обработки по артикулу с колонки 0 */ $query = \Drupal::database()->select('commerce_product_variation__field_excele_artikul', 'cv_fea'); $query->fields('cv_fea', ['entity_id', 'revision_id', 'bundle', 'field_excele_artikul_value', 'langcode']); $query->where('field_excele_artikul_value = :name', [':name' => $rowFromExcel[0]]); $result = $query->execute()->fetchAll(); $ids = []; // все ид вариантов foreach ($result as $item){ $ids[] = $item->entity_id; } // загружаем все варианты $variations = \Drupal\commerce_product\Entity\ProductVariation::loadMultiple($ids); //считаем их количество $cont = count($rowFromExcel); //из колонки цены удаляем все записи (кстати цена должна быть без копеек) $price_new = preg_replace('/([^0-9]+)/','', $rowFromExcel[$cont - 1]); /** @var \Drupal\commerce_product\Entity\ProductVariation $variation */ foreach ($variations as &$variation){ // в полученную из коллекции сущностей по артиклу вариантов записываем цену в нужном формате // валюту можно брать из настроек магазина
$variation->setPrice(new \Drupal\commerce_price\Price($price_new, 'RUB')); $variation->save(); } $context['results'][] = implode(',', $ids); // Optional message displayed under the progressbar. $context['message'] = t('Running Batch "@id" @details', ['@id' => implode(',', $ids), '@details' => $operation_details] ); } В итоге получили, что каждая строка обрабатывает все записи вариантов по артикулу и присваивает им нужную цену с валютой RUB. Процесс отображается пользователю. Можно менять строки начальной и конечной строки, не обновляя старые. Как это работает для менеджераЕсли цена меняется, менеджер исправляет ее в Google таблице. После этого в админке сайта необходимо выполнить одну простую команду «Обновить цены». В результате на сайте автоматически цены будут обновлены. Надеемся, статья была для вас полезна, и вы смогли по инструкции настроить самостоятельно синхронизацию цен и упростить работу себе и менеджерам. Подписывайтесь на наш Телеграм-канал, где мы рассказываем, как делаем дизайн, нейминг, продвижение, публикуем короткие инструкции и т.д. Будем рады новым подписчикам. Пишите комментарии, если остались вопросы по настройкам. |
Ключевые теги
Рекомендуем прочитать:
Подписаться на новые статьи
Свежие записи
-
09 November
-
09 October
-
30 August