gifts2017

Прямой обмен с БД интернет-магазина на Joomla (JoomShopping, VirtueMart)

Опубликовал Павел Островский (32ops) в раздел Обмен - Интеграция с WEB

Многие при выборе CMS для интернет-магазина не в последнюю очередь ориентируются на конечную стоимость решения. И вот выбор сделан в пользу Joomla, оплачены работы по созданию сайта, дизайн отличный, все хорошо, вот только одна деталь – обмен с 1С либо вообще не налажен, либо не устраивает из-за особенностей ведения учета в 1С, из-за низкой скорости обмена. Возникает задача настройки/оптимизации/адаптации обмена с интернет-магазином. За такую задачу готов взяться далеко не любой программист 1С, так как необходимы знания в смежной области, решения, которые предлагается адаптировать, зачастую защищены. В данной статье описывается методика обмена с интернет–магазином, не требующая от программиста оперировать понятиями незнакомой для него области. Предлагается работать с интернет-магазином как с базой данных. Благо, в интернет-магазинах под Joomla все необходимое для этого есть.

Итак, нам необходим интернет магазин под Joomla, для данной статьи выбран JoomShopping, т.к. автор считает его наиболее перспективным, в отличие от все более отстающего VirtueMart-а. Но, в принципе, технология для других магазинов отличается лишь структурой БД, и никаких препятствий для её использования нет.

Если у Вас нет интернет-магазина, но вы хотите на практике опробовать обмен, инструкция по его созданию на хостингах timeweb и radiushost приложена к данной статье. Будем считать, что магазин уже у нас есть.

Нам нужно установить ODBC драйвер для соединения с базой данных. Для его установки нужно скачать и установить MicrosoftVisualC++ 2010 RedistributablePackage (x86) с http://www.microsoft.com/en-us/download/confirmation.aspx?id=5555, скачать и установить MySQL Connector/ODBC 5.3.4 http://dev.mysql.com/downloads/connector/odbc/

Можно приступать к разработке. При установке соединения с базой данных важно установить кодовую страницу 1251, для нормального отображения русских символов. Для этого в строке соединения указываем «STMT=SET CHARACTER SET CP1251». В итоге подключение к БД будет выглядеть примерно так:

СтрПодключения = "DRIVER={MySQL ODBC 5.3 Unicode Driver};";
СтрПодключения = СтрПодключения+"SERVER="+Хост+";";
СтрПодключения = СтрПодключения+"Database="+ИмяБазы+";";
СтрПодключения = СтрПодключения+"Uid="+Логин+";PWD="+Пароль+";Option=3;STMT=SET CHARACTER SET CP1251";
Соединение=Новый COMОбъект("ADODB.Connection");
Соединение.Open(СтрПодключения);

При составлении запросов к БД есть один немаловажный нюанс. Поля, содержащие некоторые нехорошие символы, нужно брать в кавычки. Таких полей будет большинство, поэтому лучше брать в кавычки все поля. Только кавычки эти непростые, а вот такие `<имяполя>`. Код символа таких кавычек отличается от стандартного, это необходимо учитывать. Также нужно понимать, что у всех таблиц вашей БД есть префикс, который нужно добавлять слева к имени таблицы. Пример запроса:

ТекстЗапроса="DELETE FROM "+Префикс+"jshopping_categories";
Соединение.Execute(ТекстЗапроса);

Неплохо было бы оптимизировать наши запросы к БД. Не только с точки зрения самого запроса, но и с точки зрения количества передаваемых на хост данных. Например, синхронизацию товаров мы производим по коду. Тогда схема, когда мы отправляем для каждой номенклатурной позиции запрос «update», либо «insert» , будет неоптимальной. Причем для определения, какой из запросов мы будем делать, нам придется предварительно прочитать все коды из таблицы товаров. Как раз для такого случая подходит синтаксис «INS ERT ON DUPLICATE KEY UPDATE”, который позволяет обновить значения полей, если строка с таким ключом уже существует, либо, если нам не нужно ничего делать с уже существующими в БД строками «INS ERT IGNORE». В итоге запрос на обновление всей таблицы за один запрос будет выглядеть следующим образом «INS ERT IN TO <таблица> (<поле1>,..,<полеn>)VALUES (<Знач1>,...,<Значn>),...,(<Знач1>,...,<Значn>) ON DUPLICATE KEY UPDATE <поле1>=VALUES(<Знач1>),...,<полеn>=VALUES(<Значn>)». Такие запросы будут работать наиболее эффективно, правда при этом необходимо следить за тем, чтобы длина строки текста запроса не превысила максимум, установленный для базы. Пример формирования запроса:

Запрос=Новый Запрос;
Запрос.Текст="ВЫБРАТЬ
             |	КатегорииПапок.Папка КАК ПапкаНоменклатуры,
             |	КатегорииПапок.КодКатегории
             |ПОМЕСТИТЬ ВТ_КатегорииПапок
             |ИЗ
             |	&КатегорииПапок КАК КатегорииПапок
             |ГДЕ
             |	КатегорииПапок.Выгружать
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             |	Товары.Ссылка КАК Номенклатура,
             |	ВТ_КатегорииПапок.КодКатегории КАК КодКатегории,
             |	Товары.Наименование КАК Наименование,
             |	Товары.Код КАК Код,
             |	ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
             |	ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) - ЕСТЬNULL(ТоварыВРезервеНаСкладахОстатки.КоличествоОстаток, 0) КАК Количество
             |ИЗ
             |	ВТ_КатегорииПапок КАК ВТ_КатегорииПапок
             |		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Товары
             |			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
             |					,
             |					ТипЦен = &ТипЦен
             |						И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ЦеныНоменклатурыСрезПоследних
             |			ПО Товары.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
             |			ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
             |					,
             |					Качество = ЗНАЧЕНИЕ(Справочник.Качество.Новый)
             |						И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ТоварыНаСкладахОстатки
             |			ПО Товары.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
             |			ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(, ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ТоварыВРезервеНаСкладахОстатки
             |			ПО Товары.Ссылка = ТоварыВРезервеНаСкладахОстатки.Номенклатура
             |		ПО ВТ_КатегорииПапок.ПапкаНоменклатуры = Товары.Родитель
             |ИТОГИ
             |	МИНИМУМ(Наименование),
             |	МИНИМУМ(Код),
             |	МИНИМУМ(Цена),
             |	МИНИМУМ(Количество)
             |ПО
             |	Номенклатура";
Запрос.УстановитьПараметр("КатегорииПапок",КатегорииПапок);
Запрос.УстановитьПараметр("ТипЦен",Цена);
Результат=Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
	ТекстЗапросаНоменклатура="INSERT "+?(ОбновлятьСтаруюНоменклатуру,"","IGNORE ")+"IN TO "+Префикс
	+"jshopping_products (`product_id`,`product_date_added`,`date_modify`,`product_publish`,`name_ru-RU`,`description_ru-RU`,`short_description_ru-RU`,`product_price`,`product_quantity`) VALUES ";
	ПустойЗапрос=Истина;
	ТекстЗапросаКатегорииНоменклатуры="INSERT IGNORE IN TO "+Префикс
	+"jshopping_products_to_categories (`product_id`,`category_id`) VALUES ";
	
	ВыборкаНоменклатура=Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	Пока ВыборкаНоменклатура.Следующий() Цикл
		ТекстЗапросаНоменклатура=ТекстЗапросаНоменклатура+?(ПустойЗапрос,"",",")+"("
		+ВыборкаНоменклатура.Код+",'"+Формат(ТекущаяДата(),"ДФ='yyyy-MM-dd HH:mm:ss'")
		+"','"+Формат(ТекущаяДата(),"ДФ='yyyy-MM-dd HH:mm:ss'")
		+"',1,"""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
		+""","""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
		+""","""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
		+""","+Формат(ВыборкаНоменклатура.Цена,"ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0")
		+","+Формат(ВыборкаНоменклатура.Количество,"ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0")+")";
		Выборка=ВыборкаНоменклатура.Выбрать();
		Пока Выборка.Следующий() Цикл
			ТекстЗапросаКатегорииНоменклатуры=ТекстЗапросаКатегорииНоменклатуры+?(ПустойЗапрос,"",",")+"("
			+Выборка.Код+","+Выборка.КодКатегории+")";
			ПустойЗапрос=Ложь;
		КонецЦикла;

	КонецЦикла;
КонецЕсли;
Если Не ПустойЗапрос Тогда
	Если ОбновлятьСтаруюНоменклатуру Тогда
		ТекстЗапросаНоменклатура=ТекстЗапросаНоменклатура+" ON DUPLICATE KEY UPDATE `product_publish`=1,`date_modify`=VALUES(`date_modify`),`name_ru-RU`=VALUES(`name_ru-RU`),`description_ru-RU`=VALUES(`description_ru-RU`),`short_description_ru-RU`=VALUES(`short_description_ru-RU`),`product_price`=VALUES(`product_price`),`product_quantity`=VALUES(`product_quantity`)";
	КонецЕсли;
	Соединение.Execute(ТекстЗапросаНоменклатура);
	Соединение.Execute(ТекстЗапросаКатегорииНоменклатуры);
КонецЕсли;

Структуру таблиц и полей БД интернет-магазина легко определить при помощи phpMyAdmin в панели управления сайта. К статье приложена обработка для выгрузки товаров в интернет-магазин JoomShopping из 1С УТ 10.3 или КА 1.1. Данная обработка также будет работать в конфигурациях, которые используют структуру хранения остатков и цен номенклатуры, аналогичную УТ. Поскольку обработка предназначена для демонстрации работы с интернет-магазином как с базой данных, она имеет ряд ограничений, например, не выгружаются картинки. Ограничения и инструкция по использованию данной обработки находится в приложении к статье.

Скачать файлы

Наименование Файл Версия Размер
Обработка 28
.epf 17,96Kb
13.07.15
28
.epf 17,96Kb Скачать
Инструкция 17
.rtf 94,83Kb
13.07.15
17
.rtf 94,83Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Александр Шкураев (salexdv) 14.07.15 17:24
Обратите внимание на это. Работу с базой сайта можно будет сделать еще удобнее и понятнее.
2. Павел Островский (32ops) 15.07.15 05:29
3. Админ (Bodyk) 28.09.15 17:57
4. Павел Островский (32ops) 29.09.15 06:33
(3) Bodyk, Да, не работает. Я это указал. "К статье приложена обработка для выгрузки товаров в интернет-магазин JoomShopping из 1С УТ 10.3 или КА 1.1.". Есть необходимость в обработке для УТ11? В принципе могу дописать, только ведь это не полноценный обмен, обработка просто демонстрирует возможности 1с обмена с интернет-магазинами на Joomla.
5. Юрий Водич (YuriFm) 20.11.15 16:57
Было время, использовал JoomShopping, по простой причине, бесплатный, достаточно хороший функционал, простое и интуитивно понятное расширение joomla. Вообщем отлично, плюсую!
6. Павел Островский (32ops) 20.11.15 18:57
(5) Спасибо! Планирую написать нормальный обмен для обычных форм, если реализация окажется удачной, то и для управляемых. Хотелось бы узнать, какие интернет-магазины сейчас пользуются наибольшим спросом.
7. WellMaster (WellMaster) 22.01.16 14:10
{ВнешняяОбработка.ОбменССайтом.МодульОбъекта(170)}: Ошибка при вызове метода контекста (Open)
Соединение.Open(СтрПодключения);
по причине:
Произошла исключительная ситуация (Microsoft OLE DB Provider for ODBC Drivers): [Microsoft][Диспетчер драйверов ODBC] Источник данных не найден и не указан драйвер, используемый по умолчанию

Использую последние joomla и joomShoping.
Развернуто все на timeweb.
Подозреваю, что неправильно указал настройки в обработке.
В частности вопрос: правильно ли в поле Хост указывать адрес своего сайта?
Имя базы и префикс не вызывают сомнений.
Логин и пароль = написано, что совпадает с именем базы. И логин и пароль?
8. WellMaster (WellMaster) 22.01.16 14:49
(7) WellMaster,
Сам и отвечу: помогло http://www.forum.mista.ru/topic.php?id=711224 (нужен 32-х битный драйвер, даже если винда х64)
9. Павел Островский (32ops) 24.01.16 09:02
10. Алексей Андреев (Saldor) 07.08.16 07:25
Не мог бы, кто нибудь помочь. Вот в 1с, написано по выгрузке через модуль прямого обмена с БД, через HTTP туннель. Начало выгрузки в 18:46:38
7142
Выгрузка была успешно завершенна в 18:46:51
На сайт было выгруженно: 1 позиций

По resmon смотрю, трафик идет, а на сайт ничего не выкладывается.

В access log, вот что:

188.162.229.87 - - [02/Aug/2016:19:04:18 +0300] "GET /tunnel.php?check HTTP/1.1" 200 7 "-" "-"
188.162.229.87 - - [02/Aug/2016:19:04:19 +0300] "POST /tunnel.php HTTP/1.1" 200 289 "-" "Mozilla/3.0 (compatible; Indy Library)"
188.162.229.87 - - [02/Aug/2016:19:04:20 +0300] "POST /tunnel.php HTTP/1.1" 200 34 "-" "Mozilla/3.0 (compatible; Indy Library)"
188.162.229.87 - - [02/Aug/2016:19:04:21 +0300] "POST /tunnel.php HTTP/1.1" 200 289 "-" "Mozilla/3.0 (compatible; Indy Library)"
188.162.229.87 - - [02/Aug/2016:19:04:22 +0300] "POST /tunnel.php HTTP/1.1" 200 6 "-" "Mozilla/3.0 (compatible; Indy Library)"

Сам модуль забирает с начала моей базы по нажатию скачать типы цен , вот отсюда:

1,"1","Description"
2,"1","No. of Cores"
4,"1","test 1"
5,"1","test 2"
6,"1","test 3"
7,"1","test 4"
8,"1","test 5"
9,"1","test 6"
10,"1","test 7"
11,"1","test 8"
3,"1","Clockspeed"
1,"5","Description"
2,"5","No. of Cores"

База в размере меняется на пару сот килабайт, после обмена, но товар не появляется.

P.S: Как разберусь, выложу полную статью c файлами по обмену с БД через HTTP тунель.
Прикрепленные файлы:
OpenCart_v3cr.epf
tunnel.php
11. Алексей Андреев (Saldor) 07.08.16 08:40
И да, на другой базе все работало нормально.