Миграции базы данных в 1С-Битрикс: быстро, правильно, надежно. Миграции битрикс


Миграции базы данных в 1С-Битрикс: быстро, правильно, надежно

Если Вы разрабатываете проекты на 1С-Битрикс с привлечением двух и более программистов, то Вам сюда.

ИНТЕРВОЛГА делится с сообществом веб-разработчиков своим крутым инструментом для АВТОМАТИЧЕСКОЙ миграции БД в 1С-Битрикс.

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

При использовании нашего модуля, время на выполнение релиза и перенос изменения БД, сокращается с нескольких часов до 10-20 минут (при отсутствии конфликтов).

Среди огромного разнообразия данных в 1С-Битрикс: Управление Сайтом для первого раза мы выбрали следующие сущности.

Для сопоставления записей между несколькими БД нужно выбрать уникальный ID. Родные числовые ID не подходят на эту роль — ими нельзя управлять и они могут различаться в разных БД.

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

Сущность XML ID миграции
Группа пользователей STRING_ID
Тип почтового события LID + EVENT_NAME
Почтовый шаблон md5(EMAIL_FROM+EMAIL_TO+EVENT_NAME+сайты)
Язык LID
Культура NAME
Сайт LID
Настройка шаблона сайта SITE_ID+TEMPLATE+md5(CONDITION)
UF-поле md5(ENTITY_ID+FIELD_NAME)
Вариант списка UF-поля XML_ID
highload-блок TABLE_NAME
Поле highload-блока md5(highload-блок+FIELD_NAME)
Вариант списка поля highload-блока XML_ID
Тип цены XML_ID
Тип плательщика md5(NAME+сайты)
Группа свойств заказа md5(NAME+Тип плательщика)
Свойство заказа md5(CODE+Тип плательщика)
Вариант свойства заказа md5(VALUE+Свойство заказа)
Тип инфоблока ID
Инфоблок XML_ID
Свойство инфоблока Инфоблок+XML_ID
Вариант свойства инфоблока Инфоблок+XML_ID
Право на инфоблок md5(Инфоблок+Группа)
Форма редактирования Инфоблок+несколько полей формы
Поле раздела инфоблока md5(Инфоблок+FIELD_NAME)
Вариант списка поля раздела инфоблока XML_ID

Конфигурирование модуля

Конфигурацию можно изменить в файле /local/migrato/config.xml . Кстати, папку /local/migrato/ нужно обязательно добавить в репозиторий — помимо конфигурации здесь же будут и XML-файлы экспорта. Файл редактируется только вручную через FTP/SSH/файловый менеджер БУС. Синтаксис файла представлен в таблице:

Узел Родительский узел Описание
<config> - Корневой
<module> <config> Настройки миграции модуля
<name> <module> Название модуля
<entity> <module> Сущность для миграции
<name> <entity> Название сущности
<options> <config> Мигрируемые настройки
<exclude> <options> Регулярное выражение для исключения настроек из миграций  

Команды модуля

Для устранения проблем с таймаутом сервера (и чтобы придать тёплую ламповую атмосферу) вся работа с модулем после установки вынесена в командную строку. Точка входа:   <папка модуля>/intervolga.migrato/tools/run.php (в примерах для краткости будет обозначена как run.php ).

Интерфейс модуля в командной строке

Синтаксис простой: $ php run.php команда [опции]

Доступные команды:

  1. validate (проверка XML ID)
  2. autofix (автоматическое исправление ошибок XML ID)
  3. export (экспорт данных из БД в XML)
  4. import (импорт данных из XML в БД)
  5. log (вывод логов последней запущенной команды)

Служебные команды (для разработчиков новых сущностей):

  1. generate (генерация демо-контента)
  2. unittest (тестирование модуля)

Доступные опции:

  1. -W или --win (изменить кодировку на win-1251)
  2. -U или --utf (изменить кодировку на UTF-8)
  3. -F или --fails (расширенный вывод ошибок после выполнения команды)
  4. -v (краткий отчёт по работе команды)
  5. -vv (подробный отчёт по работе команды)

Проверка XML ID (команда validate)

Модуль читает config.xml и проверяет, чтобы у всех экземпляров сущностей были заданы корректные XML ID. Команда ничего не изменяет в БД. Критерии корректного XML ID:

  1. Не пустой.
  2. Не целиком числовой.
  3. Попадает под регулярное выражение /^[a-z0-9\-_#.]+$/i (допустимы буквы латинского алфавита, цифры, тире, подчёркивание, решётка, точка).
  4. XML ID не должен повторяться в пределах сущности .

Автоматическое исправление ошибок XML ID (команда autofix)

Исправление ошибок XML ID — ответственный шаг, потому и вынесен в отдельную команду. Внимание: процесс может привести к модификации БД . Для всех найденных ошибок XML ID вызывается генератор XML_ID, создающий уникальный код сущности.

Экспорт в *.xml-файлы (команда export)

  1. Модуль записывает текущие настройки всех перечисленных модулей в файлы. Файлы складываются в /local/migrato/<название модуля>/option.xml .
  2. Модуль проверяет XML ID. Работа продолжается только если нет ошибок.
  3. Для каждой записи из перечисленных сущностей модуль создаёт файл: /local/migrato/<название модуля>/<название сущности>/data-<xml id>.xml
  4. Если данные были удалены — в соответствующем файле проставляется атрибут deleted=true в узле <data>

Импорт из *.xml-файлов (команда import)

  1. Модуль выполняет разбор и импорт настроек в БД.
  2. Модуль проводит проверку данных. Работа продолжается только если нет ошибок.
  3. Модуль читает data-файлы и импортирует записи.
  4. Модуль проверяет, остались ли сущности с неразрешёнными зависимостями. Если они есть — это ошибка.
  5. Модуль удаляет файлы, помеченные атрибутом deleted=true .
  6. Модуль проставляет ссылки в данных.
  7. Обновление поискового индекса, urlrewrite, сброс кэша // Вы ведь не забываете делать все это при релизах :) ?

Вывод логов предыдущей команды (команда log)

Если при выполнении одной из предыдущих команд произошла ошибка, увидеть их можно командой log . Использовав опцию --fails можно отфильтровать все записи, оставив только сообщения об ошибках. Если же вам удобнее работать с БД, то все ошибки сохраняются в таблице intervolga_migrato_log .

Генерация демо-контента (команда для разработчиков generate)

Помните, трава раньше была зеленее, мороженое вкуснее а модуль DEFA Tools был бесплатным? Его генератор демо-контента мы воспроизводить, конечно, не стали, но добавить по 2 записи в каждую сущности команда generate может. Команда полезна для разработчиков новых сущностей.

Тестирование модуля (команда для разработчиков unittest)

Вторая команда, полезная для разработчиков (и тестировщиков). Исполняется сценарий.

  1. export
  2. Файлы XML копируются в /local/migrato_old/
  3. import
  4. export
  5. diff папок /local/migrato/ и /local/migrato_old/

Если все сущности работают правильно, diff будет пустым. Если же нет — это значит, что в коде сущности есть ошибка и она импортируется в базу неправильно.

Формат XML файлов

Синтаксис XML-файлов миграции настроек модулей

Узел Родительский узел Описание
<options> - Родительский узел
<option> <options> Настройка
<name> <option> Название настройки
<value> <option> Значение настройки
<site> <option> Сайт, для которого задано значение

Синтаксис XML-файлов миграции данных

Узел Родительский узел Описание
<data> - Родительский узел. Атрибут deleted говорит, что данные были удалены
<xml_id> <data> XML ID данных
<dependency> <data> Узел зависимости
<reference> <data> Узел ссылки
<field> <data> Узел простого поля
<name> <dependency>

<reference> <field>

Название поля
<value> <dependency> <reference> <field> Значение поля

Как пользоваться модулем

Чтобы начать использовать модуль необходимо на боевом сайте создать оригинальный слепок БД:

  1. Установить модуль intervolga.migrato
  2. Настроить /local/migrato/config.xml
  3. validate
    1. autofix при необходимости или ручное исправление XML ID в БД
  4. export
  5. Добавить папку /local/migrato/ в git (он же у вас уже есть)
  6. git commit & git push
  7. Снять бекап с prod и развернуть на dev1, dev2 ...

Чтобы подготовить миграцию на песочнице devX после окончания работы над задачей:

  1. validate
    1. autofix при необходимости или ручное исправление XML ID в БД
  2. export
  3. git commit & git push

Выполнить миграцию (релиз) на боевом сайте:

  1. validate
    1. autofix при необходимости
  2. export (вдруг на бою были неучтённые в git’е изменения?)
    1. git commit при необходимости
  3. git pull
    1. разрешение конфликтов, если возникли
    2. git push , если возникли конфликты
  4. import

Использование XML ID вместо ID в коде

Пытливый читатель-программист может задать вопрос: как же теперь писать код, если использовать ID — плохо, а XML ID миграции не всегда совпадает с XML ID сущности?

Модуль предоставляет API для получения ID по XML ID: \Intervolga\Migrato\Data\BaseData::getPublicId($xmlId)

Метод использует кеширование, так что о производительности не стоит беспокоиться.

Если вы используете константы для обращения к сущностям по ID, то вам только и нужно — сделать следующую замену.

Было

Стало

А вот второе изменение принять будет не так просто. Визуальный редактор БУСа при работе с компонентами генерирует код, в котором явно фигурируют “магические” неуникальные числовые ID.

Вот за такое хочется Битрикс от души поругать. Генерация кода зашита очень глубоко и кастомизировать её нет никакой возможности. Мы не стали придумывать хитрых способов подмены такого кода и просто ввели правило — визуальным редактором для редактирования компонентов не пользуемся. Программист один раз настраивает компонент, потом заменяет ID на XML ID миграции и никаких няш-мяш. Если знаете способ лучше — расскажите в комментариях, с радостью примем на вооружение.

Выполнение примера из других модулей

И, напоследок, выполнение общего примера нашим модулем. Сразу после установки проверили все записи на наличие внешних ключей и исправили ошибки:

Теперь можно создавать dev сайты для разработчиков - клонируем prod и обязательно делаем первый снимок базы данных (выполняем команду экспорт).

После того, как каждый программист выполнит свою задачу на своем сайте, он делает экспорт. Так как изменения были произведены только в ИБ модуле, то и экспортировать другие модули нет смысла (Настройка config файла).

После программист делает коммит экспортируемых файлов, и перед тем как вытолкнуть файлы на удаленный репозиторий необходимо проверить, может другой программист выполнил задание быстрее (git pull). На этом шаге, возможна ситуация возникновения конфликта. Что же, тут есть 2 пути, смотря как Вам удобней работать. Если у вас git на серверах разработки, при конфликте появится такое предупреждение:

Открываете файл, например с помощью vim (vi local/migato/iblock/type/...) и выбираете, кто из программистов не врет.

После этого индексируете файлы и коммитете.

Есть еще второй путь, если у вас гит только на локальной машине, и синхронизируете все файлы с помощью гита, но на локальной машине. На примере показано возникновение конфликта в IDE PHPStorm.

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

После того, как все программисты вытолкнули свои изменения, версия базы данных в системе управления версий стабилизируется. Это значит, что наступило время делать релиз. После которого, чтобы обновить любой сайт (будь то сайт для разработки или prod), достаточно трех глобальный вещей:

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

Вместо выводов

Инструмент для миграции изменений БД жизненно необходим при ответственной командной работе над проектами. До сегодняшнего дня эта задача в мире 1С-Битрикс решалась очень плохо.

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

www.intervolga.ru

Скрипты миграций для 1С-Битрикс. Добавление/обновление пользовательских свойств

@param @doc https://dev.1c-bitrix.ru/api_help/main/reference/cusertypeentity/index.php @doc https://dev.1c-bitrix.ru/api_help/main/reference/cuserfieldenum/index.php global $APPLICATION; $info = array(); function oGetMessage($key, $fields) { $messages = array( 'USER_TYPE_UPDATE' => 'Пользовательское свойство #FIELD_NAME# [#ENTITY_ID#] успешно обновлено', 'USER_TYPE_UPDATE_ERROR' => 'Ошибка обновления пользовательского свойства #FIELD_NAME# [#ENTITY_ID#]: #ERROR#', 'USER_TYPE_ADDED' => 'Пользовательское свойство #FIELD_NAME# [#ENTITY_ID#] успешно добавлено', 'USER_TYPE_ADDED_ERROR' => 'Ошибка добавления пользовательского свойства #FIELD_NAME# [#ENTITY_ID#]: #ERROR#', 'USER_TYPE_ENUMS_SET_ERROR' => 'Ошибка установки значений пользовательского свойства #FIELD_NAME# [#ENTITY_ID#]: #ERROR#', ); return isset($messages[$key]) ? str_replace(array_keys($fields), array_values($fields), $messages[$key]) : ''; } @TODO $aUserFields = array( array( 'ENTITY_ID' => 'USER', 'FIELD_NAME' => 'UF_HOODS', 'USER_TYPE_ID' => 'enumeration', 'SORT' => 500, 'MULTIPLE' => 'N', 'MANDATORY' => 'N', 'IS_SEARCHABLE' => 'N', 'SETTINGS' => array( 'DEFAULT_VALUE' => '', 'SIZE' => '40', 'ROWS' => '3', ), 'EDIT_FORM_LABEL' => array( 'ru' => 'Вытяжки', 'en' => 'Hoods', ), 'LIST_COLUMN_LABEL' => array( 'ru' => 'Вытяжки', 'en' => 'Hoods', ), 'LIST_FILTER_LABEL' => array( 'ru' => 'Вытяжки', 'en' => 'Hoods', ), 'VALUES' => array( array( 'VALUE' => 'К1', 'XML_ID' => 'К1', 'DEF' => 'N', 'SORT' => 100, ), array( 'VALUE' => 'К2', 'XML_ID' => 'К2', 'DEF' => 'N', 'SORT' => 200, ), ), ), ); $oUserTypeEntity = new CUserTypeEntity(); foreach ($aUserFields as $aUserField) { $resProperty = CUserTypeEntity::GetList( array(), array('ENTITY_ID' => $aUserField['ENTITY_ID'], 'FIELD_NAME' => $aUserField['FIELD_NAME']) ); if ($aUserHasField = $resProperty->Fetch()) { $idUserTypeProp = $aUserHasField['ID']; if ($oUserTypeEntity->Update($idUserTypeProp, $aUserField)) { $info[] = oGetMessage('USER_TYPE_UPDATE', array( '#FIELD_NAME#' => $aUserHasField['FIELD_NAME'], '#ENTITY_ID#' => $aUserHasField['ENTITY_ID'], )); } else { if (($ex = $APPLICATION->GetException())) { throw new \Bitrix\Main\SystemException(oGetMessage('USER_TYPE_UPDATE_ERROR', array( '#FIELD_NAME#' => $aUserHasField['FIELD_NAME'], '#ENTITY_ID#' => $aUserHasField['ENTITY_ID'], '#ERROR#' => $ex->GetString(), ))); } } } else { if ($idUserTypeProp = $oUserTypeEntity->Add($aUserField)) { $info[] = oGetMessage('USER_TYPE_ADDED', array( '#FIELD_NAME#' => $aUserField['FIELD_NAME'], '#ENTITY_ID#' => $aUserField['ENTITY_ID'], )); } else { if (($ex = $APPLICATION->GetException())) { throw new \Bitrix\Main\SystemException(oGetMessage('USER_TYPE_ADDED_ERROR', array( '#FIELD_NAME#' => $aUserField['FIELD_NAME'], '#ENTITY_ID#' => $aUserField['ENTITY_ID'], '#ERROR#' => $ex->GetString(), ))); } } } $obEnum = new CUserFieldEnum; $valuesEnums = array(); foreach ($aUserField['VALUES'] as $arUserFieldEnum) { $valuesEnums[] = $arUserFieldEnum + array('USER_FIELD_ID' => $idUserTypeProp); } $userTypeEnumsIterator = CUserFieldEnum::GetList(array('SORT' => 'ASC'), array('USER_FIELD_ID' => $idUserTypeProp)); if ($userTypeEnumsIterator->SelectedRowsCount()) { $valuesEnumsNews = array(); foreach ($valuesEnums as $idValueEnum => $valueEnum) { $userTypeEnumsHasIterator = CUserFieldEnum::GetList(array(), array('USER_FIELD_ID' => $idUserTypeProp, 'VALUE' => $valueEnum['VALUE'])); if ($arTypeEnumsHasIterator = $userTypeEnumsHasIterator->Fetch()) { $valuesEnumsNews[$arTypeEnumsHasIterator['ID']] = $valueEnum; } else { $valuesEnumsNews['n' . $idValueEnum] = $valueEnum; } } } else { $valuesEnumsNews = array(); foreach ($valuesEnums as $idValueEnum => $valueEnum) { $valuesEnumsNews['n' . $idValueEnum] = $valueEnum; } } if (!$obEnum->SetEnumValues($idUserTypeProp, $valuesEnumsNews)) { $strError = ''; if ($ex = $APPLICATION->GetException()) { $strError = $ex->GetString(); } throw new \Bitrix\Main\SystemException(oGetMessage('USER_TYPE_ENUMS_SET_ERROR', array( '#FIELD_NAME#' => $aUserField['FIELD_NAME'], '#ENTITY_ID#' => $aUserField['ENTITY_ID'], '#ERROR#' => $strError, ))); } } echo implode("<br>\n", $info);

www.olegpro.ru

Миграция из Битрикс в amoCRM

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

“Ависта модуль” - сибирская компания, оказывающая комплексные услуги по проектированию, строительству и комплектации быстровозводимых зданий административно-бытового и промышленного назначения, обратилась в RocketSales с задачей построения новой CRM-системы, в основе чего был переход из “Битрикс24” в amoCRM.

Преимущества amoCRM – удобная CRM-система с множеством возможностей:

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

Переход из одной CRM-системы на другую подразумевал миграцию базы контактов, компаний и сделок из “Битрикс24” в amoCRM за последние два года. Также заказчику требовался перенос базы телефонных контактов и истории взаимоотношений с клиентами за все время работы.

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

Аудит отдела продаж

С помощью доработки получилось достичь корректности всех передаваемых данных - заявки автоматически попадали в amoCRM с указанием точки входа. Если были UTM-метки указанные в адресной строке сайта при переходе по рекламной ссылке, то данные метки попадали в специальные поля в CRM-системе.

Проведена миграция контактов, компаний и сделок из “Битрикс24” в amoCRM с прикрепленными событиями. При переносе базы данных были сохранены взаимосвязи сущностей. Настройка импорта всей информации из карточек заявок, клиентов (это было необходимо для того, так как в карточках старой CRM у клиента были свои, вручную созданные поля), проверено, чтобы такие же поля были созданы в настройках карточки лида/сделки в новой системе.

Настройка воронки продаж

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

Интеграция CRM с веб-сайтом

С помощью доработки получилось достичь корректности всех передаваемых данных - заявки автоматически попадали в amoCRM с указанием точки входа. Если были UTM-метки указанные в адресной строке сайта при переходе по рекламной ссылке, то данные метки попадали в специальные поля в CRM-системе.

Установка и настройка виджетов

Клиенту был установлен виджет-пак "Интерфейс" от RocketCRM - комплекс виджетов, который делает работу с интерфейсом amoCRM быстрее и удобнее.

IP-телефония

Интеграция amoCRM с OnlinePBX позволила настраивать схему звонков. Если в отдел продаж звонит новый клиент, телефоны по очереди звонят у менеджеров, пока один из них не ответит. Если клиент уже общался с компанией, он всегда попадает на своего менеджера. Заказчику была настроена автоматическая отправка SMS на мобильный номер менеджера с номером телефона клиента при недозвоне клиента.

Подготовка к перемещению базы данных

Заказчику требовалось, чтобы процесс переноса базы данных представлял собой миграцию сущностей “Сделка”, “Контакт”, “Компания” из “Битрикс24” в amoCRM с прикрепленными событиями и с сохранением взаимосвязей сущностей при переносе базы.

Перед перемещением базы данных из “Битрикс24” в amoCRM была проведена подготовка которая отвечала на следующие вопросы:

Всего из “Битрикс24” в amoCRM необходимо было перенесли порядка 8 тысяч контактов и компаний, около 1,5 тысяч сделок, а также все истории сделок, лиды и звонки.

Перемещение базы данных

После выполнения всех подготовительных действий, программистами RocketSales был написан скрипт, - с его помощью из “Битрикс24” клиента в amoCRM была скопирована и перенесена база данных.

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

Для успешного импорта были выбраны обязательные поля, - Имя, Фамилия, Отчество были объединены в единое поле, всем остальным полям в порядке очередности выставили соответствие, после чего данные из “Битрикс24” загрузились в amoCRM по заданному алгоритму.

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

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

Настройка перенесенной базы данных

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

Важной задачей в миграции базы из битрикса в amoCRM было сохранение телефонной базы. При работе в старой CRM-системе телефония в компании клиента была настроена таким образом, что в “Битрикс24” не фиксировалась вся история общения с клиентом. Менеджеры компании использовали мобильные телефоны, что не позволяло вернуться к записи переговоров и вести статистику звонков.

В качестве решения мы предложили использовать телефонию OnlinePBX - это офисная АТС, работающая с несколькими SIP-операторами и CRM-системами.

В результате миграции вся телефонная база из “Битрикс24” была перемещена в amoCRM. Также была сохранена история телефонных звонков в истории сделки.

Итоги переноса базы данных из “Битрикс24” в amoCRM

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

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

При переносе базы компании “Ависта модуль” из “Битрикс24” в amoCRM все данные клиента были сохранены. Сам процесс миграции базы данных занял около 12 часов. Менеджеры стали работает в одном окне, в том числе звонить по IP-телефонии. Сотрудники стали быстрее обрабатывать запросы клиентов.

rocketcrm.bz


Prostoy-Site | Все права защищены © 2018 | Карта сайта