Содержание
Задача. Есть интернет-магазин на Woocommerce и база 1С: Предприятия. Компания продает товары в разных городах и имеет там свои склады. Главной целью является сделать интеграцию WordPress с 1С. В 1С есть учет по складам, а в Woocommerce их по умолчанию нет. Поэтому на сайте нужно реализовать эти склады, чтобы покупатель мог указывать где он будет забирать товар при заказе. Также необходимо настроить геотрагетинг так, чтобы на странице товара отображались для выбора только склады в выбранном или определившемся городе [Изображение 1].
Решение. Для решения задачи по настройке обмена данными между 1С и Woocommerce со складами и геотаргетингом, будем использовать следующие плагины:
- EDI — Обмен данными между WooCommerce и 1С — обмен данными между WooCommerce и приложением для бизнеса «1C:Предприятие 8. Управление торговлей» (и совместимыми).
- Stock Locations for WooCommerce — плагин для реализации складов в Woocommerce.
- WT Geotargeting — плагин определяет и выводит город пользователя.
Создание складов в Woocommerce
Создаем склады плагином Stock Locations for WooCommerce. Он создает таксономию location
, терминами которой и являются складские помещения. В товаре отмечаем нужные склады и указываем количество в запасе для каждого. Лучше предворительно почитать о настройке на странице плагина.
Алгоритм настройки складов:
- Общие настройки.
- Создание и донастройка складов.
- Добавление складов в товары.
Общие настройки
Включить управление запасами: WooCommerce Настройки — Товары — Запасы.
Общие настройки плагина: WooCommerce — Stock Locations for WC — Settings [Изображение 2.1]. Основные опции на которые стоит обратить внимание:
- Отображать местоположение склада в разделе.
- Управление запасами на странице товара.
- Показывать количество на складе при выборе местоположения во внешнем интерфейсе.
- Восстановить значение запаса местоположения для отмененный статуса заказа.
- Восстановить значение запаса местоположения для неудачный статуса заказа.
Создание и донастройка складов
Для добавления новых складов перейти Товары — Stock locations. При создании склада, указыть его название, обязательно включить «Автоматическое распределение заказов» и устанавить Приоритет местоположения на 1 или больше (тут стоит ознакомиться с инструкциями), но я ставил везде просто единицу. Если не включить автоматическое распределение, тогда после оформления заказа нужно будет вручную в заказе вводить количество заказанного товара (оно подсвечивается какой склад был выбран, но в поле стоит 0 и нужно будет его заменять на соответствующее количеству в заказе).
Второй, обязательный момент, необходимо включить (активировать) склад после его добавления, иначе он просто не будет отображаться в списке складов на сайте, несмотря на то, что в товаре он будет задан [Изображение 2.2].
Импорт складов
Если складов очень много, то их вомозжно будет быстрее импортировать, предварительно выгрузив из 1С. Можно сделать таблицу по примеру Таблицы №2, где сразу указать нужные параметры.
cf_1s_id_location | Term Name | slw_auto_allocate | slw_location_priority | slw_location_status | id_city_locations |
---|---|---|---|---|---|
66c5f3f2-e3b9-11eb-b762-a26573e75a7a | Главный Склад (ул. Коммуны 11) | 1 | 1 | 1 | 1013 |
18031d85-befd-11ed-9a7f-1831bfcdce8e | Склад №1 (ул. Коммуны 28) | 1 | 1 | 1 | 1013 |
d6959bf9-0fc7-11ec-b077-1831bfcdce8e | Склад №2 пр.Успенского 11 | 1 | 1 | 1 | 1014 |
- Term Name — название склада.
cf_1s_id_location
— пользовательское поле для id склада из 1С (*создадим и рассмотрим подробнее в разделе по синхронизации с 1С).slw_auto_allocate
— мета-поле плагина, которое включит «Автоматическое распределение заказов».slw_location_priority
— мета-поле плагина, установит Приоритет местоположения.slw_location_status
— мета-поле плагина, активирует склад.id_city_locations
— пользовательское поле для id города (*рассмотренно в разделе по настройке геотаргетинга).
Добавление складов в товары
Добавляются склады на странице редактирования товара (Изображение 2.3):
- В блоке Location отметить необходимые склады и обязательо сохранить товар, иначе не появятся поля с запасами.
- В блоке Данные товара — Складские помещения заполнить поля Stock Qty с запасами по каждому складу.
* — общая сумма в запасе должна совпадать с числом во вкладке Запасы — поле Количество, иначе могут быть проблемы - Если цена по всем складам одинаковая, то поле Stock Price оставляем пустым.
Настройка синхронизации 1С с Woocommerce
Как и было сказано ранее, для синхронизации сайта с 1С используем плагин «EDI — Обмен данными между WooCommerce и 1С». Не смотря на то, что для включения складов в синхронизацию нужны будут доработки самого плагина, разберем для начала общий алгоритм настроек сайта и 1С, как при обычном импорте:
- После установки плагина в разделе Woocommerce — Настройки синхронизации с 1С [Изображение 3.1] нужно задать Логин и Пароль (любые), отметить что импортировать, скопировать адрес из «URL сайта для обмена с 1С»
- В 1С нужно перейти в «Интеграция с Интернет-магазином» [Изображение 3.2] Настройки — Интеграции — Каналы продаж — Интернет-магазин.
- Во вкладке Авторизация указать:
Тип сайта — Другой;
Выгружать файлы обмена — На сайт;
Адрес сайта, Логин и Пароль — из настроек на странице плагина. - Чтобы изображения товаров передавались их нужно включить в настройках 1С — Интеграция с интернет-магазином — Товары — Выгружать присоединенные файлы.
- Нажать «Проверить подключение» и если соединение установленно, то в списке «Синхронизация данных» пункт «Выполнить полный обмен данными» и дождаться окончания импорта.
Смотреть Изображения 3.1 и 3.2
Некоторые моменты по работе с плагином EDI:
- Если на сайте до импорта были какие-то товары, то после импорта они перейдут в состояние «На утверждении».
- После импорта в папке
/wp-content/uploads/edi-1c/
должны быть файлыoffers.xml
иimport.xml
- Внизу страницы настроек плагина есть ссылка Просмотреть лог, где можно посмотреть ошибки при выполнении импорта.
- Для ручного обновления из offers.xml и import.xml понадобится установка WP-CLI.
WP-CLI нужен при ручном обновлении файлов offers.xml и import.xml. Это может понадобиться при отладке или доработке, чтобы не грузить каждый раз из 1С все товары, а изменить offers.xml с меньшим количеством товаров. После установки WP-CLI на сайт понадобятся некоторые команды. Работа с WP-CLI ведется через терминал. Для загрузки offers.xml выполните в терминале:
wp edi checkauth
иwp edi init
- Скопируйте файл в папку /wp-content/uploads/edi-1c/
wp edi import offers.xml
Для import.xml — аналогично. Почему загружать файл нужно после wp edi init? Потому, что при выполнении этой команды все файлы из той папки удаляются.
Доработки плагина «EDI» под склады
Первой задачей является научить плагин брать информацию по складам и добавлять ее в товар, а вторая задача — настроить синхронизацию из сайта в 1С, учитывая выбранные склады (экспорт заказов). Разделим доработку на две части.
Доработка плагина под импорт данных о складах
Сперва нам нужно узнать в каком виде приходят данные о товарах на сайт. После выгрузки товаров изучаем файл /wp-content/uploads/edi-1c/offers.xml
. В моем случае структура была такая как в Код №3.1
Код №2.1: Пример файла offers.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
<?xml version="1.0" encoding="UTF-8"?> <КоммерческаяИнформация xmlns="urn:1C.ru:commerceml_210" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ВерсияСхемы="2.08" ДатаФормирования="2023-11-10T23:50:42"> <ПакетПредложений СодержитТолькоИзменения="false"> <Ид>35f1b205-ac10-2fe2-b56c-d07a566f5f63#</Ид> <Наименование>Пакет предложений (Основной каталог товаров)</Наименование> <ИдКаталога>35f1b205-ac10-2fe2-b56c-d07a566f5f63</ИдКаталога> <ИдКлассификатора>35f1b205-ac10-2fe2-b56c-d07a566f5f63</ИдКлассификатора> <Владелец> <Ид>66c5f3ee-e3b9-11eb-b762-a26573e75a7a</Ид> <Наименование>ИП Иванов Иван Иванович</Наименование> <ИНН>744500123456</ИНН> <ПолноеНаименование>ИП Иванов Иван Иванович</ПолноеНаименование> </Владелец> <ТипыЦен> <ТипЦены> <Ид>d6959bf8-0fc7-11ec-b077-1831bfcdce8e</Ид> <Наименование>Розничные</Наименование> <Валюта>руб</Валюта> <Налог> <Наименование>НДС</Наименование> <УчтеноВСумме>true</УчтеноВСумме> </Налог> </ТипЦены> </ТипыЦен> <Склады> <Склад> <Ид>66c5f3f2-e3b9-11eb-b762-a26573e75a7a</Ид> <Наименование>Главный Склад (ул. Коммуны 11)</Наименование> </Склад> <Склад> <Ид>18031d85-befd-11ed-9a7f-1831bfcdce8e</Ид> <Наименование>Склад №1 (ул. Коммуны 28)</Наименование> </Склад> <Склад> <Ид>d6959bf9-0fc7-11ec-b077-1831bfcdce8e</Ид> <Наименование>Склад №2 пр.Успенского 11</Наименование> </Склад> </Склады> <Предложения> <Предложение> <Ид>4c0a5b10-0fcb-11ec-b077-1831bfcdce8e</Ид> <Наименование>Алмазная мозайка стразами SL-1027-541</Наименование> <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE"/> <Штрихкод>6968795565933</Штрихкод> <Артикул>751</Артикул> <Цены> <Цена> <Представление>249 руб. за шт</Представление> <ИдТипаЦены>d6959bf8-0fc7-11ec-b077-1831bfcdce8e</ИдТипаЦены> <ЦенаЗаЕдиницу>249</ЦенаЗаЕдиницу> <Валюта>руб</Валюта> <Единица>шт</Единица> <Коэффициент>1</Коэффициент> </Цена> </Цены> <Количество>11804</Количество> <Склад ИдСклада="66c5f3f2-e3b9-11eb-b762-a26573e75a7a" КоличествоНаСкладе="10804"/> <Склад ИдСклада="18031d85-befd-11ed-9a7f-1831bfcdce8e" КоличествоНаСкладе="1000"/> <Склад ИдСклада="d6959bf9-0fc7-11ec-b077-1831bfcdce8e" КоличествоНаСкладе="0"/> </Предложение> <Предложение> <Ид>4c0a5b11-0fcb-11ec-b077-1831bfcdce8e</Ид> <Наименование>Молоко сгущ бут.880гр</Наименование> <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE"/> <Артикул>519</Артикул> <Цены> <Цена> <Представление>49 руб. за шт</Представление> <ИдТипаЦены>d6959bf8-0fc7-11ec-b077-1831bfcdce8e</ИдТипаЦены> <ЦенаЗаЕдиницу>49</ЦенаЗаЕдиницу> <Валюта>руб</Валюта> <Единица>шт</Единица> <Коэффициент>1</Коэффициент> </Цена> </Цены> <Количество>1000</Количество> <Склад ИдСклада="66c5f3f2-e3b9-11eb-b762-a26573e75a7a" КоличествоНаСкладе="300"/> <Склад ИдСклада="18031d85-befd-11ed-9a7f-1831bfcdce8e" КоличествоНаСкладе="500"/> <Склад ИдСклада="d6959bf9-0fc7-11ec-b077-1831bfcdce8e" КоличествоНаСкладе="200"/> </Предложение> </Предложения> </ПакетПредложений> </КоммерческаяИнформация> |
В примере видно, что склады организованы подобно категориям, у каждого склада есть Наименование
и Ид
, а указание о количестве товара на складе задается через ИдСклада
. Выходит, что идентификатор склада в 1С является ключевым моментом. Поэтому нам необходимо его указать в наших складах. Для этого сделаем кастомное мета-поле для таксономии location
— cf_1s_id_location
и присвоим соответствующие значения каждому складу (об этом упоминалось выше в Импорте складов).
Далее, мы используем хук-фильтр плагина 'edi_parse_offer_xml_object'
и хук 'edi_offer_before_save'
, где получаем данные по складам из разбора XML и добавляем их при сохранении товара [Код №3.2]. Код можно разместить в functions.php
или сделать отдельным плагином.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/* === Доработка EDI плагина импорта товаров из 1С === */ ## Получаю данные товара. Фильтр для разбора XML данных о складах add_filter( 'edi_parse_offer_xml_object', 'qfurs_add_location_to_product_xml_object', 10, 2); function qfurs_add_location_to_product_xml_object( $product_data, $xml_data ) { // В этом методе вы должны извлечь данные о складах из XML и добавить их в $product_data. $product_data['offer_locations'] = array(); if ( isset($xml_data['Склад']) and is_array($xml_data['Склад']) ) { foreach ( $xml_data['Склад'] as $offer_location ) { $offer_location_data = array( 'ИдСклада' => $offer_location['@']['ИдСклада'], 'КоличествоНаСкладе' => $offer_location['@']['КоличествоНаСкладе'], ); $product_data['offer_locations'][] = $offer_location_data; } } return $product_data; } ## Добавляю данные товару. Хук для обработки данных перед сохранением add_action( 'edi_offer_before_save', 'qfurs_location_product_before_save', 20, 2); function qfurs_location_product_before_save( $product, $product_data ) { // В этом методе вы должны обработать данные о складах перед сохранением. // id товара $post_id = $product->get_id(); // Убираем привязку поста ко всем складам и в конце добавим те, где есть запасы wp_delete_object_term_relationships( $post_id, 'location' ); foreach ( $product_data['offer_locations'] as $offer_location_data ) { // id склада из 1C $location_id_1c = $offer_location_data['ИдСклада']; // Количество на складе $quantity = $offer_location_data['КоличествоНаСкладе']; // Поиск термина склада с полем cf_1s_id_location, соответствующего текущему $location_id_1c из xml. $term_location = get_terms(array( 'taxonomy' => 'location', 'hide_empty' => 0, 'meta_query' => array( array( 'key' => 'cf_1s_id_location', 'value' => $location_id_1c, ), ), )); if (!empty($term_location)) { // Получить id склада в WP $location_id = $term_location[0]->term_id; // Имя поля мета-данных (количество в запасе) $meta_key = '_stock_at_' . $location_id; // Присвоить товару склад. true - оставить связь с другими терминами if ( $quantity > 0 ){ wp_set_object_terms($post_id, $location_id, 'location', true); } // Обновить мета-поле товара количество в запасе для склада update_post_meta($post_id, $meta_key, $quantity); } } } |
'edi_parse_offer_xml_object'
— фильтр для разбора XML данных о складах, где мы проверяем есть ли в массиве $xml_data склад и если есть, то добавляем его в массив $product_data.'edi_offer_before_save'
— хук для обработки данных перед сохранением, где мы перебираем поллученные ранее склады, ищем по их id склад, который на сайте и добавляем в товар соответствующие данные.На данном этапе это всё. При импорте товары уже должны распределяться по складам.
Доработка экспорта заказов
Для экспорта заказов необходимо в Woocommerce — Настройки синхронизации с 1С включить Экспорт заказов. Остальное по импорту можно отключить, если все товары уже импортированы. Далее Выполнить полный обмен данными в 1С.
После обмена в папке /wp-content/uploads/edi-1c/
появится файл примерно с таким названием — orders-xxxxx-xxxx-xxxx.xml
. Пример его содержимого в Коде №3.3 для одного заказа. Как видно — в теге <Документ>
размещается один заказ.
Смотреть Код №3.3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
<?xml version="1.0" encoding="UTF-8"?> <КоммерческаяИнформация xmlns="urn:1C.ru:commerceml_210" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ВерсияСхемы="2.08" ДатаФормирования="2023-12-29T02:34:41"> <Документ> <Ид>68978ac9-a5bf-11ee-ab63-a6a0b71c53da</Ид> <Номер>9223</Номер> <Дата>2023-12-28</Дата> <ХозОперация>Заказ товара</ХозОперация> <Роль>Продавец</Роль> <Валюта>руб</Валюта> <Курс>1</Курс> <Сумма>196</Сумма> <Контрагенты> <Контрагент> <Ид>d7ff5f20-9762-11ee-ab61-a6a0b71c53da</Ид> <Наименование>Иван Иванов</Наименование> <ОфициальноеНаименование> [Иванов Иван]</ОфициальноеНаименование> <ОКПО/> <Роль>Покупатель</Роль> </Контрагент> </Контрагенты> <Время>00:00:00</Время> <СрокПлатежа>0001-01-01</СрокПлатежа> <Налоги> <Налог> <Наименование>НДС</Наименование> <УчтеноВСумме>true</УчтеноВСумме> <Сумма>0</Сумма> </Налог> </Налоги> <Товары> <Товар> <Ид>e905c593-c6d2-11ed-bb4e-1831bfcdce8e</Ид> <Артикул>УФ7294</Артикул> <Наименование>Вода Славяновская миниральная 1,5л</Наименование> <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE"/> <ЗначенияРеквизитов> <ЗначениеРеквизита> <Наименование>ВидНоменклатуры</Наименование> <Значение>Товар</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>ТипНоменклатуры</Наименование> <Значение>Запас</Значение> </ЗначениеРеквизита> </ЗначенияРеквизитов> <ЦенаЗаЕдиницу>49</ЦенаЗаЕдиницу> <Количество>4</Количество> <Сумма>196</Сумма> <Единица>шт</Единица> <Коэффициент>1</Коэффициент> </Товар> <Товар> <Ид>d7ff5f34-9762-11ee-ab61-a6a0b71c53da</Ид> <Артикул/> <Наименование>SHIPPING|1|free_shipping|Бесплатная доставка</Наименование> <БазоваяЕдиница НаименованиеПолное=""/> <ЗначенияРеквизитов> <ЗначениеРеквизита> <Наименование>ВидНоменклатуры</Наименование> <Значение>Услуга</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>ТипНоменклатуры</Наименование> <Значение>Услуга</Значение> </ЗначениеРеквизита> </ЗначенияРеквизитов> <ЦенаЗаЕдиницу>0</ЦенаЗаЕдиницу> <Количество>1</Количество> <Сумма>0</Сумма> <Единица>796</Единица> <Коэффициент>1</Коэффициент> </Товар> </Товары> <ЗначенияРеквизитов> <ЗначениеРеквизита> <Наименование>Номер по 1С</Наименование> <Значение>СА-009223</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>Дата по 1С</Наименование> <Значение>2023-12-28T22:59:20</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>ПометкаУдаления</Наименование> <Значение>false</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>Проведен</Наименование> <Значение>false</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>Оплачен</Наименование> <Значение>false</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>Отгружен</Наименование> <Значение>false</Значение> </ЗначениеРеквизита> </ЗначенияРеквизитов> </Документ> </КоммерческаяИнформация> |
В Инструментах администратора 1С можно посмотреть Последний загруженный файл заказов [Изображение 3.3].
Смотреть Изображение 3.3
На сколько понимаю, то формат передачи данных о складе в заказе может быть разным, в зависимости от того как это реализованно в 1С. В моем случае, мне разработчик 1С сказал, что нужно передать в блок <ЗначенияРеквизитов>
данные о складе как название склада таким образом [Код №3.4]:
1 2 3 4 5 6 7 8 9 |
<ЗначенияРеквизитов> <ЗначениеРеквизита> <Наименование>Розничный склад</Наименование> <Значение>Склад №1 (ул. Коммуны 28)</Значение> </ЗначениеРеквизита> <!-- <ЗначениеРеквизита... Остальной код --> </ЗначенияРеквизитов> |
Итак, в папке плагина EDI e-commerce-data-interchange/src/ файл OrderQuery.php
отвечает за выходные данные XML с заказами, которые отправлюется в 1С. Функции используют шаблоны из папки e-commerce-data-interchange/src/partials/. Например, функция output_products()
отвечает за данные заказа, которые выводятся в product.xml
.
За блок <ЗначенияРеквизитов>
отвечает функция output_attributes()
и шаблон attribute.xml
. Поэтому, в функции нужно получить склад из данных заказа и добавить его на вывод [Код №3.5], а макете XML добавить шаблон для склада [Код №3.6].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/** * Output attributes. * @param array $params Parameters. * @return void */ protected function output_attributes( array $params ): void { static $xml = null; if ( is_null( $xml ) ) { $xml = file( __DIR__ . '/partials/attribute.xml', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); } $final_statuses = array( 'completed', 'cancelled', 'refunded', 'failed' ); /** * Order. * @var WC_Order $order */ $order = $params['order']; ## wpcraft_top Custom Code для /src/partials/attribute.xml foreach ( $params['order']->get_items() as $order_item ) { // Получаем id Склада в WP и его название в 1С 'cf_1s_name_location' $stock_location_wp_id = ''; $stock_location_1c_name = ''; // Данные заказа foreach ($order_item->get_meta_data() as $meta_data_item) { // Проверяем наличие нужных ключей в метаданных if ($meta_data_item->key === '_stock_location' && isset($meta_data_item->value)) { // id склада в WP $stock_location_wp_id = $meta_data_item->value; // Получаем название склада в 1С из кастомного поля $stock_location_1c_name = get_term_meta($stock_location_wp_id, 'cf_1s_name_location', true); } } } # end Custom Code $this->output_xml( $xml, array( 'is_paid' => $order->is_paid() ? 'true' : 'false', 'has_shipping' => ( (float) $order->get_shipping_total() ) ? 'true' : 'false', 'is_cancelled' => 'false', 'is_final' => $order->has_status( $final_statuses ) ? 'true' : 'false', 'status_name' => $order->get_status(), 'date_modified' => (string) $order->get_date_modified(), 'payment_method_title' => $order->get_payment_method_title(), ## wpcraft_top Custom Code Склады в xml: Название склада 'stock_location_name' => $stock_location_1c_name, #end ) ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<ЗначенияРеквизитов> <ЗначениеРеквизита> <Наименование>Розничный склад</Наименование> <Значение>{{ stock_location_name }}</Значение> </ЗначениеРеквизита> <ЗначениеРеквизита> <Наименование>Заказ оплачен</Наименование> <Значение>{{ is_paid }}</Значение> </ЗначениеРеквизита> <!-- Остальной код --> </ЗначенияРеквизитов> |
Еще, не помню уже точно зачем, но в /src/OrderQuery.php добавил проверку буферизации Код №3.8. Видимо, были какие-то ошибки/предупреждения в логах.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# В конце файла if ( ! $this->return ) { flush(); ob_flush(); } # Заменить на if ( ! $this->return ) { // Проверяем, включена ли буферизация вывода if ( ob_get_length() > 0 ) { flush(); ob_flush(); } } |
Всё, можно протестировать заказ, синхронизировать и посмотреть Последний загруженный файл заказов — есть ли там изменения.
По поводу файла orders_xxx.xml. В моем случае, в последнем файле заказов видно что новые данные приходят, и склады отображались в системе 1С. Но на сайте в том файле orders_xxx.xml изменений нет. Скорей всего, так происходит потому что тот файл формируется в 1С, а потом уже приходит на сайт.
Может быть полезным. Вот что содержат массивы $params['order']
и $order_item
:
$params[‘order’]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
<?php { "id": 9196, "parent_id": 0, "status": "completed", "currency": "RUB", "version": "8.2.1", "prices_include_tax": false, "date_created": { "date": "2023-12-11 12:59:53.000000", "timezone_type": 1, "timezone": "+00:00" }, "date_modified": { "date": "2023-12-11 13:00:06.000000", "timezone_type": 1, "timezone": "+00:00" }, "discount_total": "0", "discount_tax": "0", "shipping_total": "0", "shipping_tax": "0", "cart_tax": "0", "total": "245", "total_tax": "0", "customer_id": 1, "order_key": "wc_order_lSImQV8IiGAfR", "billing": { "first_name": "Иван", "last_name": "Иванов", "company": "", "address_1": "г. Солнечный пр. Свободы 2", "address_2": "", "city": "Солнечный", "state": "Солнечная область", "postcode": "000000", "country": "RU", "phone": "+78003000000" }, "shipping": { "first_name": "Иван", "last_name": "Иванов", "company": "", "address_1": "г. Солнечный пр. Свободы 2", "address_2": "", "city": "Солнечный", "state": "Солнечная область", "postcode": "000000", "country": "RU", "phone": "" }, "payment_method": "bacs", "payment_method_title": "Прямой банковский перевод", "transaction_id": "", "customer_ip_address": "45.133.61.00", "customer_user_agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.124 YaBrowser/22.9.3.892 Yowser/2.4 Safari/537.36", "created_via": "checkout", "customer_note": "", "date_completed": { "date": "2023-12-11 13:00:06.000000", "timezone_type": 1, "timezone": "+00:00" }, "date_paid": { "date": "2023-12-11 13:00:06.000000", "timezone_type": 1, "timezone": "+00:00" }, "cart_hash": "902c12e3c8867cf00f7182fc5d6178fb", "order_stock_reduced": true, "download_permissions_granted": true, "new_order_email_sent": true, "recorded_sales": true, "recorded_coupon_usage_counts": true, "number": "9196", "meta_data": [ { "id": 821466, "key": "is_vat_exempt", "value": "no" }, { "id": 821467, "key": "_edi_modified", "value": "1702310406" }, { "id": 821468, "key": "_slw_ts", "value": "125953" }, { "id": 821469, "key": "_slw_ep", "value": "1" } ], "line_items": { "51": {} }, "tax_lines": [], "shipping_lines": { "52": {} }, "fee_lines": [], "coupon_lines": [] } |
$order_item
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php { "id": 55, "order_id": 9199, "name": "ГСМ", "product_id": 9162, "variation_id": 0, "quantity": 7, "tax_class": "", "subtotal": "70", "subtotal_tax": "0", "total": "70", "total_tax": "0", "taxes": { "total": [], "subtotal": [] }, "meta_data": [ { "id": 516, "key": "_stock_locations", "value": [ 96 ] }, { "id": 517, "key": "_stock_location", "value": "96" }, { "id": 518, "key": "_item_stock_locations_updated", "value": "yes" }, { "id": 519, "key": "_item_stock_updated_at_96", "value": "7" }, { "id": 520, "key": "_slw_data", "value": { "96": { "location_name": "Склад №2 пр.Успенского 11", "quantity_subtracted": 7 } } } ] } |
Решение проблемы с дублированием первого изображения товара
Если при импорте первое изображение товара дублируется (прикрепляется как основное и добавляется в галерею), то в файле /src/Parsers/ProductImagesParser.php
нужно изменить $product->set_gallery_image_ids
, выбрав для галереи все id изображений кроме первого, Код №3.9.
1 2 3 4 5 6 7 |
// Было $product->set_gallery_image_ids( (array) $product_data['images'] ); // Стало $product->set_gallery_image_ids( array_slice( (array) $product_data['images'], 1 ) ); |
Решение ошибок при импорте товаров из 1С в WordPress
Проблема №1. Какое-то время на сайт товары выгружались, но потом перестали. Сначала синхронизация начиналась и спустя примерно час, в логах импорта на сайте появлялись ошибки для каждого товара вида:
2024-08-22T16:30:43+00:00 ERROR Product was not found. GUID b80b4f50-0fcc-11ec-b077-1831bfcdce8e
.
В логах 1С после попытки выгрузки товаров следующее
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
Интерактивный обмен Полный обмен 22.08.2024 18:59:54 Запуск выгрузки товаров 22.08.2024 20:07:16 Выгрузка на сайт завершилась с ошибками. Ответ сервера: 504 <html> <head><title>504 Gateway Time-out</title></head> <body> <center><h1>504 Gateway Time-out</h1></center> <hr><center>nginx-reuseport/1.21.1</cent... <html> <head><title>504 Gateway Time-out</title></head> <body> <center><h1>504 Gateway Time-out</h1></center> <hr><center>nginx-reuseport/1.21.1</center> </body> </html> import.xml: Произошла ошибка на стороне сервера. Получен неизвестный статус импорта. Ответ сервера: <html> <head><title>504 Gateway Time-out</title></head> <body> <center><h1>504 Gateway Time-out</h1></center> <hr><center>nginx-reuseport/1.21.1</center> </body> </html> 22.08.2024 20:09:01 offers.xml Пакет успешно выгружен на сайт. 22.08.2024 20:09:01 Завершено формирование файлов выгрузки товаров Выгружено товаров: 6 049 предложений: 6 033 картинок: 1 741 файлов: 0 |
Удалось решить обращением в техподдержку хостинга. Всё заработало после того как освободил место на хостинге (т.к. уже заканчивалось) и в ТП сделали изменения в настройке сервера, вот что ответили:
Ошибка 502 обычно указывает на проблему взаимодействия между веб-сервером (в вашем случае, сервер, который обрабатывает запросы на выгрузку товаров) и upstream сервером (то есть сервером, который фактически обслуживает эти запросы).
Удаление директивы «keepalive 2» может помочь в случае, если эта ошибка вызвана проблемами с установлением или поддержанием постоянного соединения с upstream сервером. Внесли соответствующие изменения в конфигурацию сервера. Попробуйте проверить сейчас.
Настройка геотаргетинга со складами
Наша цель — настроить геотаргетинг таким образом, чтобы в товарах в списке складов были доступны для выбора только те, которые соответствуют выбранному или определившемуся городу (пример в Изображении 1). Например, если у компании сеть магазинов во многих городах, по несколько штук в каждом, то нет необходимости показывать пользователю сотни точек где забрать товар. Можно вывести только те, которые находятся в текущем городе.
Решение. Настроить WT Geotargeting, привязать к складам города и отображать только соответствующие городу.
Алгоритм настройки геотаргетинга по складам:
- Установить плагин WT Geotargeting (Pro) и загрузить в него города
- Создать пользовательское поле для склада и привязать к каждому город.
- Написать php-скрипт, который будет брать id текущего города и создаст массив соответствующих ему складов.
- Написать js-скрипт, который, используя массив соответствующих локации складов, будет оставлять в списке складов только нужные.
Посмотреть общую настройку WT Geotargeting и скачать список городов можно здесь. После активации плагина в системе будет создан тип записи «Регионы», где можнно будет увидеть города которые мы загрузили. Если каких-то городов не хватает, то можно создать по аналогии с существующими.
Второй этап. Создать пользовательское поле cf_city_location
для таксономии location
(склады), в ACF это будет: Тип поля — Объект записи; Фильтрация по типу записей — Регион. Далее нужно отредактировать каждый склад, назначив ему необходимый город.
Третий этап. Создаем в папке с темой файл /js/wt-stock-location-select.js
и подключаем его в functions.php
. При подключении скрипта создадим массив arr_location_true
, который будет содержать ID складов соответствующих текущему городу и передадим его в подключаемый скрипт для дальнейшего использования на странице сайта [Код №4.1].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
## ПОДКЛЮЧЕНИЕ СКРИПТА ДЛЯ СКЛАДОВ ПО ГОРОДУ # Скрипт убирает из списка склады, кот. не соответствуют Городу add_action( 'wp_enqueue_scripts', 'wpcraft_top_add_script_stock_location',99); function wpcraft_top_add_script_stock_location() { # Скрипт оставить склады для текущего города wp_enqueue_script( 'wt-stock-location-select', get_stylesheet_directory_uri() . '/js/wt-stock-location-select.js', array('jquery'), null, true ); // Находим соответствующие склады определенному в WTGeotargeting городу $arr_location_true = []; // Массив складов, будет передоваться во фронтенд для обработки JS // region_id текущего города в системе $region_id = Wt::$obj->contacts->items['region_id']; // Получение складов товаров $terms = get_terms( array('taxonomy' => [ 'location' ]) ); // Перебор складов в товаре foreach( $terms as $term ){ // id склада $location_id = $term->term_id; // ID записи города (Регионы) привязанного к складу $city_location_id = get_field('cf_city_location', 'location_' . $location_id); // Если ID города в складе и ID текущего города равны if($city_location_id == $region_id){ $arr_location_true[] = $location_id; } } // Передаем в скрипт js-объект arr_location_true с содержимым из $arr_location_true wp_localize_script('wt-stock-location-select', 'arr_location_true', $arr_location_true); } |
Четвертый этап. В созданном и подключенном файле wt-stock-location-select.js
добавляем Код №4.2. Здесь мы получаем список складов товара и сопоставляем его со списком переданным в arr_location_true
. Если совпадает — оставляем, нет — удаляем.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* Массив arr_location_true (id складов) получает из functions.php при подключении скрипта */ document.addEventListener('DOMContentLoaded', function(){ // Выпадающий список складов var stockLocation_Option = document.querySelectorAll('#slw_item_stock_location_simple_product option'); if ( stockLocation_Option && arr_location_true.length > 0 ){ for(let i = 1; i < stockLocation_Option.length; i++){ // Если в списке складов 'arr_location_true' нет такой value опции - удалить опцию // 'value' преобразовать в число перед сравнением if( arr_location_true.includes( stockLocation_Option[i].getAttribute('value') ) ){ continue; } stockLocation_Option[i].remove(); } } }); |
Дополнение
Вместо pro версии WT Geotargeting можно попробовать использовать бесплатную из репозитория Цщквзкуыы. Но тогда самостоятельно добавить пользовательский тип записи городов, добавить нужные (можно даже импортировать какой-то список) и привязать их складам. А потом проверять их по названию с определившейся локацией и убирать ненужные склады.
Или другой вариант — без плагина. Т.е. сделать также кастомным типом записей города, привязать их, но без функции определения геолокации пользователя. Реализовать это как-то так, чтобы пользователь мог бы выбирать нужный город на странице и выдавать ему только соответствующие склады.