четверг, 11 декабря 2014 г.

Модуль импорта файлов формата YML - глобальное обновление

Модулю импорта из YML - почти год. В течение года мы выкатывали в маркетплейс исправления мелких багов, но практически не расширяли функционал модуля, хотя дописали к модулю очень много фич по индивидуальным заказам клиентов.

Переделать модуль полностью, серьезно расширить функционал - хотелось, но сдерживал страх поддержки старой версии, посредством которой у многих клиентов модуля регулярно в автоматическом режиме происходит обновление каталогов товаров от поставщиков.

После долгих раздумий и ведра выплаканных слез, мы придумали, как сделать, чтобы новая версия не зависела от старой и не ломала импорт старым клиентам. У модуля теперь 2 независимых ветки: 5.0 и 6.0  Они загружаются в одном модуле, работают на разных классах, создают в системе 2 разных, не мешающих друг другу и независимых типов импорта. IMPORT_YML и IMPORT_YML_6_0. Второй вид YML импорта загружается в текущем глобальном обновлении, никак не затрагивая работу уже существующих настроенных импортов.


Если старый клиент захочет перейти на новую версию импорта, ему нужно будет заново сделать настройки профилей импорта для его нового типа. Пока этого не сделано, у старых клиентов импорт будет работать по-старому. А новые клиенты смогут сразу настраивать YML импорт на версии 6.0


Чего нового в версии 6.0 ?

1 Самые глобальные изменения коснулись настроек импорта свойств. Раньше все свойства из YML файла записывались в одно множественное свойство, а для конкретных клиентов мы разбрасывали свойства, куда нужно, посредством кастомизации событий записи и апдейта элемента инфоблока. Это было неудобно.


В новой версии на этапе настройки импорта загружаемый файл анализируется и пользователю предлагается распределить какое поле из файла пойдет в какое свойство инфоблока. Доступен так же и вариант создания нового поля - либо строкового, либо списочного типа.

2 Еще одно важное изменение касается внешних кодов загружаемых товаров и разделов. В старой версии модуля товарам и разделам в качестве внешнего кода проставлялся идентификатор соответствующего товара или раздела из файла. Но оказалось, что у многих клиентов в системе существуют параллельно несколько видов импорта, а цифровые идентификаторы из файлов могут быть неуникальны. Поэтому мы добавили к внешним кодам префикс. В одном из ближайших обновлений мы сделаем возможным задавать этот префикс отдельно для каждого профиля импорта.



Кроме этого произошел ряд архитектурных изменений модуля, который вдальнейшем упростит для нас его поддержку и выпуск регулярных обновлений.

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

воскресенье, 30 ноября 2014 г.

1С Предприятие УТ - как обновлять модуль обмена на модифицированной конфигурации

В последнее время обновления модуля обмена с сайтом для 1С Предприятия выходят очень часто. Если текущий модуль обмена, установленный в УТ - оригинальный, обновлять его не составляет труда. Что же делать, если модуль обмена модифицирован, обмен с сайтом в целом налажен и устраивает, но есть необходимость "выцепить" какую-то новую фичу из свежего модуля обмена?

К примеру, одна из версий модуля обмена генерировала ошибку при попытке добавить штрих-код номенклатуры:

Ошибка при выполнении обработчика - 'ПередЗаписью'
по причине:
{ОбщийМодуль.Б_ОбменССайтомСервер.Модуль(411)}: Ошибка при вызове метода контекста (ЗарегистрироватьИзменения)
ПланыОбмена.ЗарегистрироватьИзменения(МассивУзловТовары, Запись.Номенклатура);
по причине:
Несоответствие типов (параметр номер '1')


Техподдержка Битрикс сообщила нам, что данная проблема известна и решена в обновлении модуля обмена. Однако просто так взять и обновить модуль обена мы не можем, так как ранее вносили в него модификации.

Находим в конфигурации место, в котором происходит ошибка. Это процедура

Процедура ЗарегистрироватьИзменения(Объект, Замещение = Ложь)

Скачиваем новый модуль обмена от сюда>>  Нажимаем setup - в ходе установки там по сути извлекается конфигурационный файл cf модуля. Открываем файл cf в конфигураторе и ищем там процедуру ЗарегистрироватьИзменения в модуле Б_ОбменССайтомСервер

Заменяем процедуру в своей конфигурации. Можно обновить и другие процедуры модуля, предварительно сравнив конфигурацию с файлом в конфигураторе через "Сравнить, объединить конфигурацию с файлом".

суббота, 29 ноября 2014 г.

1С Предприятие УТ - как сделать чтобы при импорте с сайта правильно заполнялись адреса контрагентов



Сам импорт не трогаем - адрес контрагента приходит, как приходит. Возникает проблема при последующем пересохранении контрагента - адрес слетает. Чтобы этого не случалось - подписываемся на событие:


Процедура _НовыйМодульПодпискаНаСобытиеПередЗаписью(Источник, Отказ) Экспорт
 
 ТекущийОбъект = Источник;
 Для Каждого ТекЭлемент Из ТекущийОбъект.КонтактнаяИнформация Цикл
  Если ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес ИЛИ ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты ИЛИ ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
  Иначе
   Продолжить;
  КонецЕсли; 
  Если Лев(ТекЭлемент.ЗначенияПолей, 28) = "<КонтактнаяИнформация xmlns=" Тогда
   Продолжить;
  КонецЕсли;
  Если ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.Адрес Тогда
   ТекЭлемент.Представление = ТекЭлемент.Представление;
   ТекЭлемент.ЗначенияПолей = "<КонтактнаяИнформация xmlns=""http://www.v8.1c.ru/ssl/contactinfo"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Представление="""+ТекЭлемент.Представление+"""><Комментарий/><Состав xsi:type=""Адрес"" Страна=""РОССИЯ""><Состав xsi:type=""АдресРФ""><СубъектРФ>Московская обл</СубъектРФ><СвРайМО><Район xsi:nil=""true""/></СвРайМО><Город>"+ТекЭлемент.Город+"</Город><НаселПункт xsi:nil=""true""/><Улица>"+ТекЭлемент.Представление+"</Улица><ДопАдрЭл ТипАдрЭл=""10100000"" Значение=""""/></Состав></Состав></КонтактнаяИнформация>";
  ИначеЕсли ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты Тогда
   ТекЭлемент.Представление = ТекЭлемент.Представление;
   ТекЭлемент.АдресЭП   = ТекЭлемент.Представление;                                                                                                                                                                               
   ТекЭлемент.ЗначенияПолей = "<КонтактнаяИнформация xmlns=""http://www.v8.1c.ru/ssl/contactinfo"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Представление="""+ТекЭлемент.Представление+"""><Состав xsi:type=""ЭлектроннаяПочта"" Значение="""+ТекЭлемент.Представление+"""/></КонтактнаяИнформация>";
  ИначеЕсли ТекЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон Тогда
   ТекЭлемент.Представление   = ТекЭлемент.Представление;
   ТекЭлемент.НомерТелефона   = ТекЭлемент.Представление;
   ТекЭлемент.НомерТелефонаБезКодов = ТекЭлемент.Представление;
   ТекЭлемент.ЗначенияПолей = "<КонтактнаяИнформация xmlns=""http://www.v8.1c.ru/ssl/contactinfo"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Представление="""+ТекЭлемент.Представление+"""><Комментарий/><Состав xsi:type=""НомерТелефона"" КодСтраны="""" КодГорода="""" Номер="""+ТекЭлемент.Представление+""" Добавочный=""""/></КонтактнаяИнформация>";
  КонецЕсли;
 КонецЦикла;

КонецПроцедуры

1С Предприятие УТ - Как сделать, чтобы при создании реализации на основании заказа менеджер подставлялся из заказа

...в не зависимости от того, какой пользователь вводит реализацию.

Открываем конфигуратор, раскрываем дерево конфигурации

Общие ->Общие модули ->

Добавляем новый модуль

Пишем в нем процедуру:

Процедура _НовыйМодульПередЗаписьюРеализации(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
 
 Источник.Менеджер=Источник.ЗаказКлиента.Менеджер;

КонецПроцедуры


Идем в

 -> Общие -> Подписки на события.

Добавляем новую подписку

на ДокументОбъект.РеализацияТоваровУслуг Событие ПередЗаписью

в поле Обработчик выбираем процедуру, которую мы только что написали в нашем новом модуле.


Данная модификация не снимает конфигурацию с поддержки.

вторник, 25 ноября 2014 г.

Интернет-магазин - минимизируем накладные расходы

Бытует мнение, что работать в убыток первые полгода-год после запуска интернет-магазина - это нормально, последующие годы все окупят. Это самообман, ловушка, в которую попадают многие учредители интернет-магазинов. Вряд ли расходы окупятся через месяц, но уже в первые месяцы после запуска магазина грязная прибыль за вычетом налогов должна покрывать ежемесячные регулярные расходы на содержание и развитие интернет-магазина. Чистая прибыль в этот период должна быть как минимум достаточной, чтобы в течение запланированного срока окупаемости (например, год или два года), вернулись средства, вложенные в запуск интернет-магазина. 

Каким бы ни был оборот интернет-магазина и какой бы ни была наценка на товар, накладные расходы легко могут поглотить всю полученную прибыль.

вторник, 14 октября 2014 г.

Еще раз про импорт каталога из 1С-Битрикс в 1С Предприятие и обратно

Совсем недавно я уже писала пост об импорте каталога из 1С-Битрикс в 1С Предприятие, а потом - обратно, но, не достаточно хорошо на мой нынешний взгляд структурировала информацию, хочу немного дополнить.

Итак,
1) В ситуации, когда источником данных о номенклатуре являлся сайт мы оказывались не единожды, и ни разу не было такого, чтобы у товаров на сайте не было каких-то XML_ID Обычно клиенты забивают товары на сайт не вручную, а пользуясь различными импортами, в следствии которых XML_ID - рождается. Так вот, прежде чем импортировать каталог в 1С необходимо убедиться, что все XML_ID товаров и разделов на сайте - уникальны. То есть, если есть раздел с XML_ID, к примеру, "121", то товара с XML_ID "121" уже быть не должно, потому что, когда они придут на сторону 1С - они будут записываться в справочник, а элемент справочника отличается от группы справочника только флажком, и вот такая неуникальность среди кодов разделов и товаров потом приводит к куче скрытых багов - обмен может не ругнуться.

2) Если мы используем стандартную обработку "Помощник импорта...", нужно помнить, что если не дай бог, в первый раз номенклатура загрузится как-то не так, то нам ее придется помечать на удаление и удалять перед следующим запуском обработки - что может оказаться на большой базе жутким геморроем, Поэтому сначала нужно пробовать на 1м разделе или на небольшом участке (для этого кастомайзим сторону сайта - об этом в моем предыдущем посте есть). Или дописываем сами апдейт в функции
НайтиСоздатьНоменклатуру на стороне 1С

Например, так:

Иначе
  Номенклатура=НоменклатураСсылка.ПолучитьОбъект();
  УстановитьРодителя(Номенклатура, СтрокаТовара.Группы);
  Номенклатура.Записать();
КонецЕсли;
КонецПроцедуры;

3) Успешно загрузили номенклатуру с сайта в 1С? Радоваться рано. Можно сгенерировать прикольный баг, когда обратный импорт на сайт потрет вам картинки на сайте. Для этого нужно создать узел полного обмена товарами и сделать полную выгрузку сначала в тестовый инфоблок на сайте, обрадоваться, что все хорошо пришло, скопировать его внешний код во внешний код рабочего инфоблока, снести тестовый и снова выполнить полный обмен. Вуаля - картинок нет. Примерно такая последовательность. А чтобы такого не случилось, при первом импорте в рабочий инфоблок нужно делать принудительную полную выгрузку.

среда, 24 сентября 2014 г.

Интеграция 1С Предприятия и 1С-Битрикс на новой версии модуля обмена – из опыта

Уже, наверное, 2 месяца как делаю новым клиентам интеграции 1С-Битрикс и 1С Предприятия на новой версии модули обмена. Сразу хочу отметить, что новая версия обмена – офигенная, небо и земля по сравнению с тем, что было раньше. Но мелкие острые камушки – попадаются, нужно пройти по ним, ободрав пятки, прежде чем окунуться в это море удовольствия.

Моя основная проблема с новым модулем интеграции состояла в том, что мне было лень на него переходить – за время существования старого модуля обмена, мы серьезно доразвили его для наших клиентов, допилили функционал на стороне 1С, вынесли все во внешние обработки, на стороне Битрикс запили свой модуль и почивали на лаврах. Когда приходил новый клиент, я просто находила похожий кейс, и мы дорабатывали какие-то неизбежно существующие особенности, будучи уверенными, что все пойдет, как надо.

Когда Битриксоиды выпустили новый модуль, некоторое время я присматривалась к нему, но не хотела внедрять – опасалась.

А потом летом случилось страшное - в какой-то момент мои шустрые сотрудники закончили все проекты и 3 дня сидели без дела. Дело то я им, конечно, нашла – обновили наши модули в маркете, но страх повторения этого апокалипсиса – остался. В тот момент я придумала акцию «интеграция в подарок» за покупку у меня лицензии на Битрикс Бизнес или за заключение со мной договора техподдержки на год. Акцию публиковала в разделе партнерских акций на сайте Битрикса, и она выстрелила – до сих пор слышу эхо.

Прикол был в том, что в период действия акции ею воспользовались всего 2 клиента, но потом еще долгое время клиенты приходили ко мне и говорили, что видели акцию и, хотя не успели ею воспользоваться, – решили все равно обратиться ко мне. В итоге в июле и августе на наши плечи свалилось порядка 10 интеграций. Большинство кейсов были типовыми и скучными, однако попались и интересные сложные задачи.

Передо мной встал сложный выбор – интегрировать новых сложных клиентов своим старым способом или внедрять им новый модуль обмена. К слову, новый модуль обмена на 80% покрывает те задачки, к-е раньше мы допиливали клиентам, как нестандартные. Посмотрела я на него и на наши обработки и подумала, что развивать свой модуль на стороне 1с, пытаясь угнаться за Битриксоидами – будет не выгодно. К тому же я вступила во взаимовыгодное партнерство с фирмой, к-я предоставляет 1С Предприятие в качестве «аренды приложения» и я хотела максимально упростить наше взаимодействие и конфигурирование 1с-ки клиентов.
Этот же фактор заставил меня глубже разобраться в коде конфигурации 1С УТ, и я, как обычно, переосмыслила все на новом уровне. (Кстати, у меня в команде теперь есть совершенно отдельный человечек, который занимается исключительно начальными настройками 1С УТ под разные особенности учета и документооборота).

Итак я начала внедрять новый модуль обмена, устанавливая клиентам 1С Предприятие 8.3.5, 1С УТ 11.1.6, накатывала на 1С УТ свежую версию Битриксовского дополнения, и брали свежий на момент начала работ Битрикс. Кстати, версия Битрикс была один из камушков. С него и начну.

1) Соответствие версий обмена на стороне 1С Битрикс и на стороне 1С Предприятия

Не припомню конкретных дат, когда это произошло, но в переходный период выхода новых модулей обмена на стороне Битрикс и на стороне 1С Предприятия у нас с некоторыми клиентами сложилась ситуация, когда Битрикс был обновлен до самой последней версии, а сторона 1С обновлена не была, и в связи с изменением протокола обмена – этот обмен не пошел. Помню свою панику, я даже кинулась копировать старый модуль обмена на стороне Битрикс в свое простанство имен и использовать его, но Битриксоиды, к счастью, предусмотрели решение на этот случай. На стороне Битрикс нужно ввести команды:

Настройки -> Инструменты - > Команда PHP строка
COption::SetOptionString("catalog", "DEFAULT_SKIP_SOURCE_CHECK", "Y" ;
COption::SetOptionString("sale", "secure_1c_exchange", "N" ;

И включится поддержка старой версии протокола.

2) Экспорт в 1С большого объема товаров
На одном из проектов мне нужно было выгрузить с сайта в 1С порядка 40 000 номенклатурынх позиций с картинками. Обработка «Помощник импорта» выполняла эту операцию ужасно долго – больше суток, что было непреемлемо для меня, и я переписала в ней некоторые места – вынесла запросы к базе из цикла. Об этом я писала отдельный пост. Битриксоиды обещали оптимизировать обработку в обновлениях.

3) Обратный импорт и дерево групп
На проекте того же самого клиента, когда мы стали делать интеграцию в обратную сторону у нас сложилась очень специфичная ситуация.

Изначально структура каталога была создана на сайте – не на битриксовском сайте, а на другом старом сайте заказчика на OpenCart. Залили каталог в Битрикс. (используя, кстати, наш модуль импорта из yml и модуль экспорта в yml из опенкарт, к-й я написла на базе одного из бесплатных и дарю теперь тем, кто покупает мой модуль импорта из yml в Битрикс и хочет забрать товары из магазина на OpenCart)

Залили каталог в 1С – все получилось просто отлично – группам товаров был присвоен код, к-й соответствовал внешнему коду разделов XML_ID на стороне Битрикс. Договорились с заказчиком, что далее наполняем каталог и редактируем его структуру на стороне 1С. Выполнили обратный импорт каталога, чтобы убедиться, что все ок, настроили обмен ценами и остатками, протестировали. Затем заказчик сказал, что структура каталога на сайте и в 1С – будет разной. В новом модуле обмена – можно настраивать дерево групп – и такая задача теперь вообще не проблема. Однако выяснился интересный факт – это скорее фича, а не баг, но она меня сильно смутила по-началу. Когда я на стороне 1С настроила дерево групп, я думала, что после обмена они – группы, к-е уже были импортированны на сайт до настройки дерева – возьмут и сами в соответствии с этим деревом перестроятся. Однако начали создаваться новые группы с новыми XML_ID. И это пришлось учесть.

4) Мелкие неприятности на стороне 1С
Трем клиентам внедряли 1С УТ с нуля (+ интегрировали с Битрикс конечно же). Кейсы были идентичными, и делали фактически параллельно. Я сделала одному клиенту, протестила и посадила помощницу все сделать точно так же на 2х других проектах. Начинаю тестировать – на 2х других проектах не работают стандартные отчеты. Вылетает ошибка

Индексируемые поля должны присутствовать в списке выборки
<>Сегменты.Номенклатура

Начинаю внутренне закипать и перебирать в уме все известные мне бранные выражения. Вслух молчу – проверяю. Вроде все одинаково. Разница оказалась в версиях платформы. Там, где все работало ок, версия стояла 8.3.5.1068, а там, где вылетала ошибка – стояла версия платформы 8.3.5.1119, конфигурация стояла одна и та же 1С УТ 11.1.6.26 Проблему решило включение режима совместимости с версией 8.3.4 А при установке дополнения я его обычно совсем выключала - а надо было, видимо, ставить 8.3.4 Хотя на более низких версиях платформы - в частности на 8.3.5.1068 все было ок с отключенным режимом совместимости, а я уже думала, что съем кого-нибудь.

5) Соответствия служб доставок и контрагентов – грузоперевозчиков
Эта задача у нас была неплохо и удобно решена на старом модуле, но к новому модулю старое решение не подходило совсем. На новом модуле я решила задачу с минимальной модификацией модуля обмена заказами, а именно процедуры "СоздатьОбновитьЗаказ".

Дописала там, где шло заполнение свойств заказа, возможно, не очень оптимально

СпособДоставки = ПолучитьЗначениеРеквизитаДокумента(ДокументXML.ЗначенияРеквизитов, "Способ доставки");
АдресДоставик=  ПолучитьЗначениеРеквизитаДокумента(ДокументXML.ЗначенияРеквизитов, "Адрес доставки");

//Получаем соответсвия доставок из наших доп настроек:
КлючОбъекта  = "Бедросова";
КлючНастроек = "ОбменССайтомБедросова"; 
//ИмяПользователя = ИмяПользователя();
ИмяПользователя = "SHARE";
СтруктураНастроек    = Новый Структура();
Попытка
        СтруктураНастроек = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта,КлючНастроек,,ИмяПользователя);
Исключение
        Сообщить("Нет прав на чтение доп настроек обмена.");
          КонецПопытки;
Если СтруктураНастроек = Неопределено Тогда
        Сообщить("Не вышло прочитать доп настройки обмена!");
Иначе
НайденнаяСтрока =  СтруктураНастроек.СоответствиеСпособовДоставки.Найти(СпособДоставки, "НаСайте");
Если НЕ НайденнаяСтрока = Неопределено Тогда
Заказ.СпособДоставки = НайденнаяСтрока.НаСервере;
Заказ.ПеревозчикПартнер = НайденнаяСтрока.Контрагент;
КонецЕсли;
КонецЕсли;
А дополнительные настройки - оставила во внешней обработке - так же, как описывала раньше.



6) Корректная передача валюты в заказах
Делая одному из клиентов обмен заказами, столкнулась с такой проблемой:  Обмен сам-по себе - проходит нормально, но затем заказу, пришедшему с сайта не удается изменить статус - выдавало ошибку

"Значение поля Валюта не может быть пустым"

В типовых соглашениях о продажах, используемом при обмене - валюта была указана RUB.
На сайте, вроде как, была указана такая же валюта в настройках валют.



Но в заказах, пришедших с сайта валюта была не заполнена.
Оказалось, нужно было указать валюту еще и в настройках интеграции на стороне сайта:


к сожалению, не было возможности протестировать это на мультивалютных магазинах.

7) Отбор номенклатуры по свойству товара

У одного из клиентов стояла 1С УТ 10.3.29.1, накатила на нее соответсвующий модуль обмена. При выгрузке номенклатуры из 1С на сайт нужно было сделать, чтобы выгружались только те товары, у которых определенное пользовательское свойство равно определенному значению. Сначала думала, что для этой цели можно использовать настройки отбора.



Оказалось, что нет.
Этот отбор не для отбора товаров, а общий отбор свойств. Т.е. будут выгружены только те свойства, которые в этом отборе(независимо от доп. настроек свойств).

Но в 1С  УТ 10.3 в модуле менеджера объекта плана обмена "Б_ОбменССайтом" есть процедура "НастроитьПостроительТоваров". В ней я и подправила пакет запросов, связанный с выборкой товаров для того, чтобы решить свою задачу.

9) Картинки торговых предложений

Потрясающе интересный случай - оставляю на закуску - напишу в следующий раз, как я по-новому реализовала на новом модуле свой старый кейс для магазинов одежды, где учет ведется по характеристикам – цвету и размеру.

вторник, 26 августа 2014 г.

Изменения протокола обмена между 1С-Битрикс и 1С Предприятие

Вот такую веселую ошибку при обмене заказами могут наблюдать Битрикс-администараторы, накатившие свежие обновления на Битрикс, но не обновившие модуль обмена на стороне 1С

failure Ошибка проверки источника запроса. Обновите модуль обмена.

Видимо, битриксоиды отказались от поддержки ранее описанного ими же здесь протокола обмена:

http://dev.1c-bitrix.ru/api_help/sale/orders_protocol.php


Напомню, каким раньше был протокол:

  1. Обмен заказами начинается с того, что 1С посылает http-запрос вместе с http-авторизацией следующего вида: http://<сайт>/bitrix/admin/1c_exchange.php?type=sale&mode=checkauth

    На этот запрос система 1С-Битрикс отвечает тремя строками (используется разделитель строк "\n"):
    1. слово "success";
    2. имя Cookie;
    3. значение Cookie.
    Примечание:
    все последующие запросы к 1С-Битрикс сопровождаются выставлением со стороны 1С имени и значения Cookie, полученными по команде "checkauth".
  2. Далее следует запрос 1С вида:
    http://<сайт>/bitrix/admin/1c_exchange.php?type=sale&mode=init

    В ответ 1С-Битрикс выдает две строчки:
    1. zip=yes, если сервер поддерживает обмен в zip-формате. В этом случае файлы на следующем шаге должны быть упакованы в zip-формате
      или
      zip=no, в таком случае файлы не должны быть упакованы, а передаются каждый по отдельности.
    2. file_limit=<число>, где <число> - максимально допустимый размер файла в байтах для передачи за один запрос. Если размер файла больше, то он должен быть порезан на части.
  3. Затем отправляется запрос вида:
    http://<сайт>/bitrix/admin/1c_exchange.php?type=sale&mode=query

    Сайт отдает заказы в формате CML 2. В случае успешного получения и записи заказов в 1С совершается запрос вида:
    http://<сайт>/bitrix/admin/1c_exchange.php?type=sale&mode=success 
  4. Затем из 1С отправляется запрос вида:
    http://<сайт>/bitrix/admin/1c_exchange.php?type=sale&mode=file&filename=<имя файла>
    который загружает на сервер файл обмена, посылая содержимое файла в виде POST. 

Конечно, странно, что сейчас битриксоиды полностью отказались от поддержки модуля обмена, который идет в 1С УТ 11 без дополнений

Что делать, если такое произошло на вашем проекте с ранее настроенной интеграцией? Конечно, если интеграция вашего сайта сделана без кастомизации на стороне 1С, проще всего накатить на 1С свежее битриксовое дополнение. Что же делать, если модуль обмена на стороне 1С у вас кастомизирован, и в ваши планы сейчас не входит делать всю работу на стороне 1С заново на основе нового модуля обмена (а ее придется делать заново – изменения модуля обмена глубоки, и обычным слиянием с использованием 1С-совской системы контроля версий тут не обойдешься - проверила), тогда проще использовать на стороне сайта модуль обмена, выдранный из старой версии Битрикс.

Я думаю, каждый, кто захочет сделать себе деградацию модуля обмена на стороне Битрикс – сделает ее. А я сейчас расскажу, как сделать, чтобы ваш модуль обмена на стороне сайта был зафиксирован, никогда не обновлялся, не преподносил сюрпризов вашей кастомной 1С-ке при сохранении возможности обновления всех остальных модулей.

Идем в папку /bitrix/components/bitrix/ (на сайте, на котором обмен уже настроен и версия обмена вас устраивает) и копируем компоненты обмена

catalog.export.1c
catalog.export.1c
sale.export.1c

в свое пространство имен. Соответсвенно я копирую их в папку

/local/components/bedrosova/

Далее нам необходимо скопировать классы обмена. Мы не будем их наследовать в этот раз, а сделаем копии. Заводим свой файлик, не важно по сути, где он будет лежать и как называться, к примеру, можно положить его в /local/php_interface/lib/exchange.php

Открываем файл /www/bitrix/modules/iblock/classes/general/cml2.php и копируем класс class CIBlockCMLImport в свой файлик с другим именем, например с именем CIBlockCMLImport2, аналогично поступаем с файлом CIBlockCMLExport из того же файла.

Аналогично поступаем с классом CAllSaleExport из файла /bitrix/modules/sale/general/ export.php и с классом CSaleExport из /bitrix/modules/sale/mysql/export.php (делаем ему class CSaleExport2 extends CAllSaleExport2)

Далее в наших компонентах обмена из нашего пространства имен подключаем наш файл с нашими классами-копиями, после чего заменяем в компонентах все вызовы CIBlockCMLImport, CIBlockCMLExport и CSaleExport на вызовы CIBlockCMLImport2, CIBlockCMLExport2 и CSaleExport2

После этого идем в /bitrix/admin/ содаем там новый файл 1c_exchange2.php, копируем туда содержимое файла /bitrix/modules/sale/admin/1c_exchange.php

Заменяем в нашем файле /bitrix/admin/1c_exchange2.php вызовы стандартных компонентов битрикс bitrix:sale.export.1c, bitrix:sale.export.1c и bitrix:catalog.export.1c на вызовы наших кастомных (я заменяю на bedrosova:sale.export.1c, bedrosova:sale.export.1c и bedrosova:catalog.export.1c), прописываем в 1С путь к нашему скрипту обмена /bitrix/admin/1c_exchange2.php

Наслаждаемся!
Теперь можем спокойно обновлять битрикс, и не ждать сюрпризов по части обмена с 1С.

Примечание! Наши скопированные классы продолжают использовать стандартные языковые файлы.

четверг, 31 июля 2014 г.

Импорт товаров из 1С-Битрикс в 1С Предприятие УТ 11 - опыт использования стандартного функционала

В прошлый раз, когда я делала клиенту импорт товаров из 1С-Битрикс в 1С Предприятие УТ мы с 1С-программистом делали какую-то жуткую кастомизацию по его инициативе, и от стандартного импорта там остались только рожки да ножки. Сейчас со мной работает другой 1С-программист, и мы стараемся сначала выжать максимум из стандартного функционала, а уж потом, если этого мало — переходим к кастомизации.

Итак передо мной встала задача импортировать 36 000 с хвостом товаров из 1С-Битрикс в 1С УТ 11.1.6. Битрикс обновлен до самой свежей версии, на 1С УТ установлено битриксоидовское дополнение.

Начав настраивать импорт каталога с сайта заказчика в 1С УТ я, как обычно, сделала множество открытий:

1) Уникальность рабочих наименований.
Когда у нас на сайте 36 000 товаров в 300х разделах, их наименования, естественно, не уникальны. В 1С УТ же по-умолчанию включен контроль их уникальности, в следствии чего импорт товаров через помощник импорта товаров с сайта завершается с ошибкой.
Открываем конфигурацию 1С УТ в режиме предприятия, идем в Администрирование — Настройка параметров системы — Номенклатура Снимаем галочку «Контроль уникальности...»



2) Список свойств, которые могут быть импортированы — не описан пока в документации, поэтому пришлось выявить его, почитав код обработки «Помощник импорта товаров». Это:
CML2_ARTICLE — артикул
CML2_BASE_UNIT — базовая единица
Помимо этого в тексте обработки перебираются и записываются в дополнительные сведения о номенклатуре все остальные свойства с префиксом CML2_

Для того, чтобы сайт корректно отдал эти свойства 1С-ке, в настройке свойств инфоблоков свойствам нужно задать соответствующие внешние коды:


3) Меня так же интересовал момент, предусматривает ли обработка апдейт элемента номенклатуры — или только вставку и по какому полю контролируется наличие элемента в справочнике.
Апдейта нет — только вставка.
В качестве уникального идентификатора номенклатуры используется
Номенклатура.Б_Идентификатор = СтрокаТовара.Ид;

В это ИД товара Битрикс вписывает XML_ID товара, если оно задано и обычное ID товара, если XML_ID не задано. У меня  XML_ID были заданы, так я изначально наполняла сайт заказчика через свой модуль импорта из YML файлов, предоставленных поставщиком.
Если у вас на сайте не заданы XML_ID — рекомендую их сгенерировать — к примеру, можно сделать их равными ID. Какой смысл? Это решит в дальнейшем проблему обмена в другую сторону и проблему с обменом заказами.

4) Механизм  — нужно протестировать перед финальной загрузкой, которая даже на очень мощном сервере будет длиться очень долго.

На стороне сайта я тестирую выгрузку так:
- авторизуюсь на сайте
- вбиваю в строку браузера запрос:
http://адрес_сайта/bitrix/admin/1c_exchange.php?type=get_catalog&mode=init
получаю
zip=yes
- вбиваю следующий запрос:
http://адрес_сайта/bitrix/admin/1c_exchange.php?type=get_catalog&mode=query
Сайт отдает кусочек xml-файла. Он не выглядит как xml-файл — это нормально — он не целый и не завершенный. 1С-ка когда прихоит на сайт за каталогом посылает этот запрос до тех пор, пока не заберет весь файл по кусочкам.

Однако, то, как выгружаются товары — мы видим, проверяем, выгружается ли все так, как нужно.

Далее мне необходимо как-то сначала протестировать импорт на стороне 1С Предприятия на маленьком кусочке. Потому что, если все 36 000 товаров загрузятся неправильно, потом можно успеть состариться, пока дождешься их удаления — мы ведь проапдейтить их в следующий проход импорта не сможем. Я хочу протестировать обмен сначала на 100-200х товаров — думаю, этого будет достаточно. Для этого я копирую компонент экспорта каталога catalog.export.1c в свое пространство имен.

В своем кастомном компоненте я нахожу место

elseif($_GET["mode"] == "query")
{

И дописываю:

if ($_SESSION["BX_CML2_EXPORT"]["current"]>100) $_SESSION["BX_CML2_EXPORT"]["step"]=4;

Делаю свой скрипт обмена 1c_exchange2.php, в котором подключаю свой компонент вместо стандартного.

elseif($type=="get_catalog")
{
$APPLICATION->IncludeComponent("bedrosova:catalog.export.1c", "", Array(
"IBLOCK_ID" => COption::GetOptionString("catalog", "1CE_IBLOCK_ID", ""),
"INTERVAL" => COption::GetOptionString("catalog", "1CE_INTERVAL", "-"),
"ELEMENTS_PER_STEP" => COption::GetOptionString("catalog", "1CE_ELEMENTS_PER_STEP", 100),
"GROUP_PERMISSIONS" => explode(",", COption::GetOptionString("catalog", "1CE_GROUP_PERMISSIONS", "1")),
"USE_ZIP" => COption::GetOptionString("catalog", "1CE_USE_ZIP", "Y"),
)
);
}

Мой скрипт  1c_exchange2.php будет отдавать 1С-ке только 100+N товаров. N – количество товаров, выгружаемых за 1 шаг. Вписываю в помощнике импорта адрес своего скрипта и запускаю импорт.

После того, как товары загружены — начинается загрузка картинок. На этом этапе может вывалиться ошибка «Реквизит для группы не найден» - она может возникнуть, если есть группа с таким же уникальным айдишником, как товар (на стороне сайта придется дополнительно перепроверять сквозную уникальность XML_ID групп и товаров).

Радуемся - товары успешно загрузились в 1С Предприятие УТ. У них есть наименование, артикул, привзяка к группе, картинка, а так же дополнительные свойства - в дополнительных сведениях. Когда потом с сайта придут заказы - 1С однозначно идентифицирует товары заказа по XML_ID, а складовщик посмотрит на картинку - и не ошибется при отгрузке.


Помощник импорта товаров в 1с с сайта на Битрикс — в целом пригоден для одноразовой загрузки номенклатуры  без дополнительной кастомизации. Единственное, плохо, что обработка выполняется очень медленно. Я расстрою тех, кто собирался развернуть 1С УТ на своем ноутбуке.

Но для москвичей это не проблема. Ведь в вашем городе живет и работает мой надежный  партнер Вячеслав Мишаков (тел. 8 499 70 77 118) - руководитель компании КМ Системс. Специалисты КМ Системс соберут для вас сервер под 1С Предприятие УТ, идеально подходящий для последующей синхронизации с 1С Битрикс. Ребята сами привезут к вам сервер, настроят его, установят 1С Предприятие, подключат его к локальной сети, разграничат доступ для ваших сотрудников, будут оказывать регулярную техподдержку сервера. Для тех, кто еще не созрел для покупки собственного сервера, КМ Системс предлагает разместить 1С Предприятие в их датацентре. Захожу на их сервера, чтобы интегрировать 1С Предприятие клиентов с 1С-Битрикс и радуюсь - не работа, а удовольствие.

воскресенье, 20 июля 2014 г.

Программное создание higload блока 1С-Битрикс - себе на память

$data = array(
'NAME' => str_replace('_','',trim("H".$tableName)),
'TABLE_NAME' => trim($tableName)
);
$result = \Bitrix\Highloadblock\HighloadBlockTable::add($data);
if ($result->isSuccess())
{
$ID = $result->getId();
$oUserTypeEntity    = new CUserTypeEntity();
$aUserFields    = array(
'ENTITY_ID'         => 'HLBLOCK_'.$ID,
'FIELD_NAME'        => 'UF_MYFIELD',
'USER_TYPE_ID'      => 'string',
'MULTIPLE'          => 'N',
'MANDATORY'         => 'N',
'SHOW_FILTER'       => 'I',
'EDIT_FORM_LABEL'   => array(
'ru'    => 'MYFIELD',
'en'    => 'MYFIELD',
)
);

$iUserFieldId   = $oUserTypeEntity->Add( $aUserFields );
                .....
        }
else{
       $errors = $result->getErrorMessages();
print_r($errors);
}



суббота, 19 июля 2014 г.

Как я обычно настраиваю Git репозиторий для работы с 1С-Битрикс

В простейшем варианте организации командной работы над проектом нам необходим — один основной сайт на сервере — будем называть его продакшеном, один сайт для тестирования (девелоперский сайт) — на сервере рядом с ним (дев. сайт) + по локальной копии сайта у каждого разработчика. (Девелоперских сайтов на сервере может быть несколько, но по поводу дополнительных дев. сайтов необходимо предварительно консультироваться с технической поддержкой Битрикс по поводу правомерности такой системы с точки зрения лицензионного договора). 

Каждый разработчик будет работать над проектом в своей локальной копии сайта, в отдельной ветке Git для каждой решаемой задачи. В конце дня каждый разработчик делает коммит в репозиторий, хранящийся на github.com и только один разработчик — ведущий, проверяет и объединяет ветки сначала на девелоперском сайте на сервере, а потом выкатывает полученный результат на продакшен. (По моему субъективному мнению, двоевластие на интернет-проекте — недопустимо. Даже если слияние веток и тестирование будет отнимать все рабочее время ведущего разработчика проекта — никто кроме него не должен вносить изменения на продакшен — сайт) В начале дня — разработчики обновляют свои репозитории с гитхаба. 

В случае, когда необходимо изменение структуры БД, разработчики сначала вносят изменения в своих локальных копиях, пишут список изменений ведущему разработчику, ведущий разработчик вносит их на продакшене, делает бекап БД продакшена, который затем накатывается на дев-сайт и на все локальные дев-сайты. Дополнительно настраивается репликация БД (но это уже тема для другой статьи). 

Итак, мы имеем выделенный сервер, два настроенных виртуальных хоста и установленное серверное ПО git — это, как правило, могут сделать для нас сотрудники хостинга, на котором мы покупаем сервер. 

В директории основного сайта разворачиваем бекап сайта стандартными средствами Битрикс (или руками), директория девелоперского сайта пока пусть будет пустой. 

Регистириуем корпоративный тариф на github.com Для системы, рассмотренной в данной статье, нам хватит тарифа за 25$ в месяц. Заводим приватный репозиторий, добавляем существующих пользователей githab к организации (или заводим новых пользователей) — это все делается очень прозрачно и удобно, поэтому не будем подробно заостряться на этом моменте. 

После того, как корпоративный приватный репозиторий заведен, нам нужно сделать первый коммит в него. 

Заходим по ssh на наш сервер под пользователем с правами на запись в папки сайтов, переходим в директорию, в которой мы намерены инициировать репозиторий. 

Репозиторий можно инициировать непосредственно в папке сайта (тогда важно не забыть потом защитить папку .git в файле .htaccess от скачивания), а можно инициировать его в наддиректории (вариант, когда файлы каждого сайта лежат не сразу в директории www или директории dev, а в подкатологе, к примеру, dev/httpfiles, www/httpfiles А репозитории мы инициируем соответственно в директориях www и dev. Если сервер настраивается с нуля или если админу не лень перепрописать виртуальные хосты— этот вариант предпочтительнее). 

Перед тем, как инициировать репозиторий для основного сайта, необходимо определиться, какие папки и файлы необходимо включать в репозиторий, а какие — нет — сформировать файл .gitignore. 

Пример (упрощенный) файла .gitignore для 1С-Битрикс для случая, когда репозиторий инициируется в директории сайта: 

/bitrix/backup 
/bitrix/cache 
/bitrix/crontab 
/bitrix/managed_cache 
/bitrix/managed_flags 
/bitrix/modules/*.log 
/bitrix/php_interface/crontab 
/bitrix/php_interface/dbconn.php 
/bitrix/stack_cache 
/logs 
/upload 
/.gitignore 
/.htaccess 
/urlrewrite.php 
/*.log 
/*.sql 
/*.txt 
/*.xml 
/*.dt 
То есть мы не будем контролировать изменения в папке бекапов (/bitrix/backup), папках кеша (/bitrix/cache, /bitrix/managed_cache, /bitrix/managed_flags, /bitrix/stack_cache), папках с заданиями крону (/bitrix/crontab), папке с логами (/logs), папке с загрузками (/upload). 
Папку с загрузками /upload на всех девелоперских копиях сайта, расположенных на одном с ним сервере, имеет смысл делать симлинком на папку /upload продакшен-сайта. 

Символическую ссылку в директории /dev/ — корневой директории девелоперского сайта создаем командой 

ln -s /path/to/www/upload 

К слову о символических ссылках. При конфигурировании многосайтовой системы на одном ядре 1С-Битрикс по 2му типу, папку bitrix мы так же должны будем исключить из основного репозитория. Потому что физически эта директория будет существовать только на одном сайте системы, а на других — будут символические ссылки на нее. Но так как контролировать изменения файлов этой папки все равно нужно, целесообразно будет завести для нее отдельный репозиторий. 

Файл /bitrix/php_interface/dbconn.php содержит индивидуальные для каждого виртуального хоста настройки (в частности настройки соединения с БД), поэтому этот файл мы добавляем в исключения git. 

Файл /urlrewrite.php — это файл с правилами обработки ЧПУ адресов Битрикс — он может быть перезаписан (сортируется внутри) самим движком, поэтому исключим и его. 

Файлы .gitignore и .htaccess тоже должны лежать в исключениях. В исключения так же стоит добавить файлы логов, текстовые файлы, xml-файлы – все то, что не относится непосредственно к программному коду. 

После того, как мы определились с содержимым .gitignore и создали файл .gitignore в директории будущего репозитория можно инициировать репозиторий для продакшен-сайта. Для этого нам сначала необходимо позаботиться об авторизации нашего серверного ssh-пользователя на githab — сгенерировать для него ключ. 

Выполняем команду 

ssh-keygen -t rsa -C "bitrix@имя.сайта" 

email можно вписать любой, но с email вида bitrix@имя.сайта легче идентифицировать ключ на гитхабе. 

Переходим на github.com/settings/ssh и добавляем новый ключ — данные самого ключа берём из файла /path/to/.ssh/id_rsa.pub 

Проверяем подключение: 

ssh-T git@github.com 

Инициируем репозиторий в директории основного сайта (или в наддиректории): 
переходим в /path/to/www/ и выполняем команды: 

git add README.md 
git commit -m "first commit" 
git remote add origin git@github.com:организация/имя_репо.git 
git push -u origin master 

После того, как репозиторий для основного сайта инициирован, зальем все файлы проекта в репозиторий гитхаб: 

git add . git commit -m “second commit” git push 

Теперь клонируем репозиторий в директорию девелоперского сайта: 

git clone git@github.com:организация/имя_репо.git dev 

После этого в директории девелоперского сайта создадим символическую ссылку на папку upload как было описано выше. Затем стандартными средства Битрикс сделаем бекап БД основного сайта, и развернем его на девелоперском — файл, хранящий подключение к БД при этом создастся для дев сайта автоматически. 

Теперь аналогичным образом можно создать клоны репозитория на локальных машинах разработчиков. Для этого им необходимо поставить любой комплект ПО git на свою локальную машину (командная Git строка идет в любом комплекте), запустить командную строку, сгенерировать ключ, добавить его на гитхаб, клонировать репозиторий в директорию виртуального хоста на локальной машине, а папку upload просто слить с основного сайта, накатить дамп БД с основного сайта. 

После этого можно расслабиться и наслаждаться командной работой, выстраивая с коллегами дружеские отношения без ссор и споров, оперативно откатывая некорректные изменения — без поиска виноватых. 

P/S: с некоторых пор я предпочитаю гитхабу битбукет

P/S2: 
Недавно уже холиварила на тему того, нужно ли включать папку bitrix в репозиторий после того, как появилась возможность разрабатывать темплейты, компоненты и модули в папке local. 

Меня попрекали тем, что я транслирую "устаревшие" понятия, и я даже чуть было не согласилась. Да что там - даже согласилась. Однако на проектах, которые веду - продолжала включать папку bitrix в репозиторий на всякий пожарный - оказалось - не зря. 

Вот мои новые аргументы для любителей похоливарить (кого я имею в виду - тот знает): 


1) Папка local-то появилась, а вот многие решения из Маркетплейс.Битрикс продолжают устанавливаться в папку /bitrix/modules/ Вы не считаете нужным контролировать их код? 

2) В папке local пока нельзя разрабатывать кастомные гаджеты для рабочего стола админки Битрикс.

Добавление элемента в highload блок 1С-Битрикс с проверкой существования и апдейтом - пример себе на память

function AddToHI($tableName='bedrosova_filter_sef',$parent_xml_id,$child_xml_id, $code){

$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/upload/bedrosova.log', 'a');
fwrite($fp, print_r('----------------- '.date("F j, Y, g:i a").". Поступившие данные:".PHP_EOL, true));
fwrite($fp, print_r(array('parent_xml_id'=>$parent_xml_id, 'child_xml_id'=>$child_xml_id, 'code'=>$code,), true));


if (strlen($code)<1)
{
fwrite($fp, print_r("Не передан символьный код!".PHP_EOL, true));
fclose($fp);
return false;
}

if (!preg_match("#^[aA-zZ0-9_]+$#",$code))
{
fwrite($fp, print_r("Символьный код содержит недопустимые символы!".PHP_EOL, true));
fclose($fp);
return false;
}

$HLData = \Bitrix\Highloadblock\HighloadBlockTable::getList(array('filter'=>array('TABLE_NAME'=>$tableName)));
      if ($HLBlock = $HLData->fetch())
      {
       //found highloadiblock
         
       $HLBlock_entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($HLBlock);
 
 
  if ($child_xml_id!="root"){
       

  //Зададим параметры запроса, любой параметр можно опустить
 

$main_query = new \Bitrix\Main\Entity\Query($HLBlock_entity);
$main_query->setSelect(array('*'));
$main_query->setFilter(array('UF_CATEGORY_XML_ID'=> $parent_xml_id,"UF_SEF"=>$code));

//Выполним запрос
$res_query = $main_query->exec();

//Получаем результат по привычной схеме
$res_query = new CDBResult($res_query);  
if (!$row = $res_query->Fetch())
{
//create record in Highload IBlock
$HLBlock_entity_data_class = $HLBlock_entity->getDataClass();
$arBxData = array
(
 'UF_CATEGORY_XML_ID' => $parent_xml_id,
 'UF_VALUE_XML_ID' => $child_xml_id,
 'UF_SEF'=> $code,
);
$res_query = $HLBlock_entity_data_class::add($arBxData);
}
else{
//апдейтим

$HLBlock_entity_data_class = $HLBlock_entity->getDataClass();
$arBxData = array
(
 'UF_CATEGORY_XML_ID' => $parent_xml_id,
 'UF_VALUE_XML_ID' => $child_xml_id,
 'UF_SEF'=> $code,
);
$res_query = $HLBlock_entity_data_class::update($row['ID'],$arBxData);

}

}
else{

$main_query2 = new \Bitrix\Main\Entity\Query($HLBlock_entity);
$main_query2->setSelect(array('*'));
$main_query2->setFilter(array("UF_SEF"=>$code));

//Выполним запрос
$res_query2 = $main_query2->exec();

//Получаем результат по привычной схеме
$res_query2 = new CDBResult($res_query2);  
if (!$row2 = $res_query2->Fetch())
{

$main_query = new \Bitrix\Main\Entity\Query($HLBlock_entity);
$main_query->setSelect(array('*'));
$main_query->setFilter(array('UF_CATEGORY_XML_ID'=> $parent_xml_id));

//Выполним запрос
$res_query = $main_query->exec();

//Получаем результат по привычной схеме
$res_query = new CDBResult($res_query);  
if (!$row = $res_query->Fetch())
{
//create record in Highload IBlock
$HLBlock_entity_data_class = $HLBlock_entity->getDataClass();
$arBxData = array
(
 'UF_CATEGORY_XML_ID' => $parent_xml_id,
 'UF_VALUE_XML_ID' => $child_xml_id,
 'UF_SEF'=> $code,
);
$res_query = $HLBlock_entity_data_class::add($arBxData);
}
else{
//апдейтим

$HLBlock_entity_data_class = $HLBlock_entity->getDataClass();
$arBxData = array
(
 'UF_CATEGORY_XML_ID' => $parent_xml_id,
 'UF_VALUE_XML_ID' => $child_xml_id,
 'UF_SEF'=> $code,
);
$res_query = $HLBlock_entity_data_class::update($row['ID'],$arBxData);

}



}


}
     
      }
fclose($fp);
}