Skip to main content

v1.13.0

Авторизация 

Изменена зависимость регистра в логине пользователя

Теперь логин при авторизации будет приводиться к единому виду. Например: test, Test, TEST — все значения нормализуются к одному значению. Это уменьшает процент “ложных” отказов при входе из-за раскладки/копипаста/привычек набора.

Если в базе исторически существовали учётки, отличающиеся только регистром (например, test и Test), система автоматически переименует одну из записей, добавив префикс d1_, d2_ и т.п., чтобы обе учётки остались различимыми и доступными.

Проверка сложности пароля при регистрации пользователя

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

Базовые требования: от 8 символов, наличие строчных и прописных букв, а также символов (спецзнаки). При несоответствии правилам возвращается ошибка — пароль не принимается. 

Менеджер проектов

Создание автодокументации по проекту 

Бизнес-требования

  • "Создать автодокументацию" – вызывается из контекстного меню проекта в менеджере
  • Создавать текстовый файл автодокументации (можно в PDF, можно в htm, можно в любом другом формате, хоть в Excel):
    1. Модель (таблица такая по полю такому связана с другой так-то и так-то) и источники проекта (название источника, расписание его обновления и SQL к этому источнику)
    2. Страницы (список страниц названиями, их статус – скрыто/открыто) и RLS (если есть, то списком – кому запрещено плюс идентификацию: группа/пользователь)
    3. Расчеты (таблица – название страницы, название таблицы, SQL-код таблицы)

Общее описание

Таблицы с данными:

  1. Список страниц
  2. Список виджетов с расчётами
  3. Список источников
  4. Список моделей данных
  5. Список правил RLS

Доступ к функциональности открыт только для пользователей с ролями "Админ" и "Разработчик" 

Наполнение документа

В документе должны быть следующие разделы в указанном порядке:

  • Страницы проекта
  • Визуализации проекта
  • Источники данных
  • Модели данных
  • Ограничения RLS
  • Скрипт загрузки
Страницы проекта

В разделе располагается ровно одна таблица без названия

Список столбцов:

  • Название страницы
  • Ширина
  • Высота
  • Изображение на фоне
  • Видимость
  • PLS
  • ID

Логика:

  • Для изображения на фоне указывается ссылка на изображение (при наличии, при отсутствии пишется null)
  • Видимость 2 видов: "Скрыто", если страница скрыта из навигации, и "Открыто", если страница видима
  • PLS – ограничения в доступе к странице, перечисляются все пользователи, которым ограничен доступ к странице (null, если таких нет)
  • ID – идентификатор страницы
Визуализации

В разделе располагается столько таблиц, сколько страниц есть в проекте

Название каждой таблицы: "Визуализации на странице <Название_страницы>"

Список столбцов:

  • Тип визуализации
  • Название визуализации
  • X
  • Y
  • Z
  • Ширина
  • Высота
  • Видимость
  • Блокировка
  • ID
  • Модель данных
  • SQL-код

Логика:

  • Тип визуализации соответствует названию по умолчанию виджета без цифр (например, Линейная диаграмма)
  • Название – то, которое дал пользователь
  • Z – определяет уровень виджета, где 1 – самый низ, далее выше по Z-слою
  • Видимость 2 видов: "Скрыто" и "Открыто"
  • Блокировка 2 видов: "Заблокировано" и "Разблокировано"
  • ID – идентификатор виджета
  • Модель данных – название модели, используемой для виджета
  • SQL-код – итоговый код для формирования виджета; если включены виртуальные данные, то писать "Виртуальные данные"
Источники

В разделе располагается ровно одна таблица без названия

Список столбцов:

  • Название источника
  • Подключенные таблицы
  • Задание на обновление
  • График запуска

Логика:

  • Подключенные таблицы писать списком через запятую в одной ячейке для каждого источника
  • Задание на обновление 2 видов: "Активно" (если есть задание и оно активно) и "Неактивно" (если нет задания или оно неактивно)
  • График обновлений содержит в себе крон-задание на обновление источника текстом (как в панели администратора, например 0 0 15 * *)
Модели данных

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

Название каждой таблицы: "Связи модели <Название_модели_данных>"

Список столбцов:

  • Из таблицы
  • Из столбца
  • Вид соединения
  • К таблице
  • К столбцу

Логика:

  • Для каждой связи описываются затрагиваемые ею столбцы и таблицы по аналогии со списком связей в модели данных
  • Вид соединения писать в формате: Inner/Full/Left/Right Join 
RLS

В разделе располагается столько таблиц, сколько есть правил в проекте

Название каждой таблицы: "Правило <Фильтр_правила>", например: "Правило WHERE Product_name = {{var0}}"

Список столбцов:

  • Субъект правила
  • Тип субъекта
  • Переменные
  • Значения переменных

После таблицы писать статус

Логика:

  • Статус 2 видов: "Активно" и "Неактивно"
  • Пользователи и группы записывать в один столбец, в каждой ячейке один пользователь или группа
  • Тип субъекта 2 видов: "Пользователь" и "Группа"
  • Для каждой переменной указывать то значение, которое установлено для конкретного пользователя/группы (или значение по умолчанию, если такого нет)
Скрипт загрузки

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

Поле ввода об изменениях в версии проекта

Проблема

Нет возможности описать в интерфейсе изменения в проекте для конкретной версии – если возникнет потребность в откате, то ориентироваться можно только дату/время изменения и память автора изменений.

Решение

Требования:

  • Кнопка для открытия модального окна для ввода комментария
  • В списке версий при откате проекта должны показываться комментарии к версиям текстом
  • Вводить текст может только автор изменения
Окно для ввода комментария в списке версий

Путь:

Менеджер проектов –> Навести курсор на проект –> Кнопка "инфо" на проекте ( i ) –> Вкладка "Версии"

Интерфейс в версиях:

  • В строках с версией должна находиться кнопка для открытия модального окна для написания комментария сразу после автора изменений
  • Кнопка появляется только если автор изменений = текущий пользователь (например, пользователь user001 не увидит поля ввода напротив версий, в которые вносил изменения пользователь admin228)
  • Если автор изменений не указан, то кнопка появляется для всех пользователей, имеющих права на управление данным проектом
  • Располагаются все кнопки в одном столбце (если автор не указан, то между временем изменения и полем ввода будет пустое пространство)
  • При наведении курсора на строку с текстом должно появляться всплывающее сообщение с записанным в него текстом

Интерфейс окна для комментария:

  • Название – "Создать комментарий"
  • Поле ввода текста с изменяемыми размерами. По умолчанию в поле ввода отображается "Введите комментарий", пропадает после ввода любого символа
  • Кнопка "Отмена"
  • Кнопка "Создать"

Логика:

  • Окно открывается при нажатии на кнопку
  • В поле ввода можно вводить любые символы
  • Максимальное количество символов для ввода – 1000
  • Поле ввода может менять свои размеры при перетягивании за правый нижний угол
  • Необходимо добавить проверку для видимости кнопок, открывающих модальное окно: если автор изменений = текущий пользователь, то кнопка видима, иначе скрыта
  • При наведении курсора на строку в версиях должно появляться всплывающее сообщение с текстом. Высота области сообщения зависит от введенного текста, ширина примерно равна ширине окна со строками с версиями

Путь:

Менеджер проектов –> ПКМ по проекту –> "Откатить"

Интерфейс:

  • Увеличить окно в ширину на ~25-30% (в макете указаны нужные размеры)
  • В строках с версией может находиться текст, если он оставлен в версиях этого проекта
  • При наведении курсора на строку с текстом должно появляться всплывающее сообщение с записанным в него текстом

Логика:

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

Уведомление об окончании лицензии

Бизнес-требования

  • Добавить в ячейку с пользователем (которая должна быть и в проекте, и в менеджере, и вообще во всех разделах):
    • Роль пользователя
    • Сколько осталось дней до окончания лицензии
  • Если осталось меньше 15 дней до окончания лицензии, то показывать модальное окно с сообщением, что скоро срок действия лицензии закончится + добавить значок уведомления на ячейку пользователя (например, восклицательный знак)

Логика:

  • Роль пользователя подтягивается из информации о пользователе в панели администратора
  • Информация о сроке действия лицензий и лицензий на публикации подтягивается из раздела "Лицензии" в панели администратора по следующему принципу:
    • Берётся дата окончания лицензии/лицензии на публикацию
    • Вычитается текущая дата
    • Результат в виде целого числа отображается в интерфейсе
Уведомление об окончании срока действия лицензии

Расположение:

Любая область стенда после авторизации

Интерфейс:

Модальное окно с сообщением:

  • Окно размещается по центру экрана, фон затемняется
  • Название окна "Уведомление"
  • Текстовое сообщение для админов "Внимание, срок действия лицензии [на публикации] истекает через . . . день/дня/дней. Пожалуйста, обратитесь к Вашему менеджеру для получения нового лицензионного ключа и активируйте его в панели администратора"
  • Текстовое сообщение для пользователей с другими ролями "Внимание, срок действия лицензии [на публикации] истекает через . . . день/дня/дней. Пожалуйста, обратитесь к администратору системы для продления срока действия лицензии".
  • Кнопка "Закрыть"
  • Кнопка "Перейти к лицензиям"

Иконка рядом с ячейкой пользователя:

  • Отображать значок "Восклицательный знак" на ячейке пользователя или рядом с ней
  • При наведении на значок рядом с иконкой добавлять тултип "Срок действия лицензии [на публикации] истекает через . . . день/дня/дней"

Решение

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

Необходимо добавить новое действие по событию при входе пользователя – показывать модальное окно с сообщением о скором истечении срока лицензии, если осталось меньше 15 дней.

При копировании проекта чтобы появлялся прелоадер и перекидывало в копию

Задача: Реализовать отображение прелоадера при копировании и перемещении проекта. 
При копировании проекта:
  • показывать лоадер с текстом «Проект копируется. Ожидайте» до завершения операции;
  • после завершения - автоматически открывать поток, в который был скопирован проект.

При перемещении проекта:

  • показывать лоадер с текстом «Проект перемещается. Ожидайте», 
  • после завершения - автоматически открывать поток, в который был перемещён проект.

ОР:

  • Прелоадер при копировании проекта, отображение статуса и открытие потока проекта;
  • Прелоадер при перемещении проекта, отображение статуса и открытие потока проекта;

Критерии приёмки:

  • При начале копирования/перемещения отображается прелоадер с корректным сообщением;
  • Прелоадер исчезает после завершения операции;
  • После завершения пользователь переходит в поток скопированного/перемещённого проекта;
  • Сообщения на прелоадере различаются для копирования и перемещения («копируется»/ «перемещается»).

Конструктор дашбордов 

Экспорт проекта в PDF

Бизнес-требования

  • Добавить возможность выгрузки в ПДФ
  • При выгрузке можно выбирать несколько страниц
  • Если выбрано несколько страниц, то после начала выгрузки они должны по очереди открываться, прогружаться, сохраняться в ПДФ (после чего берётся следующая страница)
  • Порядок страниц такой же как и в проекте (от порядка выбора галочек порядок страниц не зависит)
  • Размеры страниц берутся из проекта (в одном ПДФ может быть очень большая и очень маленькая страницы – это норм)
  • Как вариант – выгружать страницы по порядку в JPEG, а потом отдельно объединять JPEG-и в PDF
  • Писать поверх титульного JPEG (например, в колонтитул или водяным знаком) логин пользователя, выгрузившего страницы, и дату/время выгрузки
  • Добавить возможность присылать результат на почту 

    Решение

    Общее описание

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

    Пользовательский путь:

    • Зайти в проект с любой ролью, кроме зрителя
    • В.1. Открыть меню "Страницы" на левой панели настроек
    • В.2. Нажать ПКМ на названии любой страницы 
      • Нажать на кнопку "Экспортировать" на панели открывшегося меню
      • Выбрать формат экспорта в открывшемся окне "Экспорт страниц" – Файл (PDF)
      • Нажать кнопку "Продолжить"
      • Выбрать страницы для экспорта
      • Нажать кнопку "Продолжить"
Логика
  • Выбор страниц аналогичен выбору страниц для формирования JSON-файла
  • Порядок указания страниц не играет никакой роли
  • При запуске функции начинается формирование PDF-файла:
    • Система по очереди открывает каждую из страниц, указанных в модальном окне
    • Формируется JPEG для открытой страницы по текущему правилу формирования JPEG (обязательно включаются все виджеты и состояния фильтров на странице)
    • Размер JPEG равен размеру страницы
    • Переключение между страницами выполняется в режиме реального времени (на глазах у пользователя). При этом на экране вместо модального окна появляется окно с лоадером и сообщением "Ожидайте. Файл формируется"
    • После того, как были пройдены все страницы, они собираются в единый PDF-файл
    • Каждая страница имеет свои размеры, считаем нормальной ситуацию, когда в одном файле представлено несколько страниц разных размеров
  • Для итогового файла на первой странице размещать в колонтитул (или водяным знаком) логин пользователя, выгрузившего страницы, и дату/время выгрузки
  • Итоговый файл сохраняется на устройство пользователя в папку "Загрузки", а также отправляется на почту, если та была указана

Отправка на почту

Новый функционал, позволяющий указать почту получателя и отправить на неё экспортированный объект. Доступно только для PDF и JPG.

Интерфейс:

  • В модальном окне "Экспорт страниц" для выбора формата экспорта добавить чекбокс "Отправить на почту" под форматами экспорта. Чекбокс появляется только если выбран формат "Снимок (JPG)" или "Файл (PDF)"
  • Под чекбоксом добавить поле ввода адреса электронной почты

Логика:

  • Чекбокс доступен только для JPG и PDF
  • При нажатии на чекбокс появляется поле ввода
  • При попытке продолжить с пустым полем ввода (и активным чекбоксом) должно выдавать ошибку "Поле «Email» обязательно для заполнения" 
  • Необходимо выполнять проверку на корректность email. Если email некорректный, то при попытке продолжить выдавать ошибку всплывающим сообщением "Введен некорректный email"
  • При продолжении с корректным email система должна использовать его после формирования итогового файла и отправить на указанную почту результат

Режим презентации при просмотре проекта

Бизнес-требования

  • Настройка, позволяющая установить время между автоматическим переключением страниц по порядку их следования (отдельно подчёркиваю,  что управлять последовательностью страниц для показа можно только меняя их порядок в проекте).
  • При переходе на другую страницу (в том числе ручном) обратный отсчёт таймера начинается заново (отдельно подчёркиваю, что таймер устанавливается один на все страницы, нельзя для разных страниц указать разное время переключения).
  • Должно быть доступно зрителю, при активации раскрывает полноэкранный режим

Решение

Кнопка "Пуск", активирует режим презентации с возможностью задать время между переключением страниц. Доступна зрителям (бизнес-пользователям) дашборда.

Расположение:

Конструктор дашбордов → Верхняя панель → Правая область (рядом с иконкой профиля, чатом)

Интерфейс:

  • Кнопка в режиме просмотра/редактирования дашборда (н-р, кнопка "Play" в виде треугольника) для активации режима презентации
  • Кнопка в режиме презентации (н-р, кнопка "Stop" в виде квадрата) для завершения режима презентации. В свободном режиме выделяется фоном как кнопка при наведении. При наведении выделяется более тёмным фоном
  • Меню, появляющееся при нажатии ПКМ на кнопку активации режима презентации:
    • Всплывающее меню под кнопкой, текст "Время между переходами"
    • Поле ввода в меню с подписью "сек". По умолчанию стоит 60
    • Кнопка "Запустить"

Авторефреш страницы 

Бизнес-требования

  • Настройка, позволяющая установить интервал времени, по истечении которого будут заново отправлены запросы на получение данных (не обновление страницы, а именно get_data).
  • Таймер должен обновляться при каждой подгрузке данных (т.е., после применения фильтров или переходов между разрезами и страницами).
  • При подгрузке данных в визуализацию должен отображаться лоадер.

Решение

Расположение в интерфейсе

Меню настроек → Настройки страницы → Под секцией "Изображение"

Интерфейс

Новая секция "Автообновление страницы" с переключателем на ней (по умолчанию выключен). Внутри секции:

  • Поле ввода числа (только целые положительные значения), по умолчанию 600
  • Текст перед полем ввода (слева) – "Таймер"
  • Текст после поля ввода (справа) – "Сек"

Логика (фронт):

Минимальное значение для ввода в поле – 60. Если пользователь вводит значение меньше, оно автоматически должно увеличиваться до 60. Проверка значения выполняется после окончания ввода, когда пользователь убрал фокус из поля.

Хранить в течение сессии пользователя новый параметр timeToRefresh, который зависит от значения времени автообновления страницы:

  • Если переключатель "Автообновление страницы" выключен, то параметр равен "-1"
  • Если переключатель "Автообновление страницы" включен, то параметр равен значению из поля ввода

Отправлять запрос get_data после наступления времени, равного [Время_отправки_прошлого_get_data] + timeToRefresh.

При timeToRefresh = "-1" запрос не должен отправляться повторно.

Для каждой визуализации идёт собственный отсчёт времени. Таймер обновляется при каждой отправке get_data (например, при фильтрации).

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

Передавать параметр timeToRefresh на бэкенд в запросе PUT /api/v3/project/{projectId}/dashboard-settings (для сохранения в настройках проекта)

Бэкенд:

Добавить в БД в таблицу для проектов новый параметр для каждой страницы проекта – timeToRefresh. Приходит в запросе на обновление данных по проекту.

Диспетчер данных

Коннектор к Битрикс 

Бизнес-требования

https://apidocs.bitrix24.ru/api-reference/

  • У открытого API есть ограничения:
    • Есть несколько разных тарифов, ограничивающих кол-во строк в запросе
    • Необходимо ставить задержку между запросами, чтобы не получать эту ошибку
    • Все ошибки возвращают код, по которому их можно идентифицировать и выводить в интерфейсе:
  • Для авторизации нужны API-key, логин и пароль
    • или API-key и домен первого уровня (адрес состоит из названия битрикса пользователя и фиксированного домена)
    • API-key можно получить с админского аккаунта в настройках
  • Нужны все GET-методы из CRM:
    • Сделки
    • Лиды
    • Контакты
    • Компании
    • Коммерческие предложения
      • Нужен один GET из БП и роботов – Получить список бизнес-процессов
      • Нужны три GET из Задач:
        • Поля задачи
        • Получить список задач
        • История задачи
      • В параметрах запроса должна быть возможность указать, с какой даты загружать (обязателен для заполнения)
      • Учесть оптимизацию запросов
      • Предупреждать пользователя о лимитах
      • Выбирать поля для фильтрации через раскрывающийся список, а не ручным вводом (на изучить, если есть возможность получать из Битрикс список полей)
      • Тестовое подключение
      • Предпросмотр результата

      Решение

      *Все параметры, вводимые пользователем в интерфейсе, в запросах указаны в угловых скобках: <ПАРАМЕТР>

      Ограничения API

      Интенсивность запросов:

      • Каждый входящий запрос от приложения увеличивает условный "счетчик запросов" на стороне Битрикс24
      • Как только значение "счетчика" превышает пороговое значение Х, каждый следующий входящий запрос блокируется. Приложение в ответ получает статус  503 с кодом ошибки Query_limit_exceeded
      • Параллельно значение счетчика автоматически уменьшается на Y раз в секунду
      • Значения X и Y зависят от тарифного плана в Битрикс:
        • 5 и 250 для тарифа Энтерпрайз
        • 2 и 50 для остальных тарифов (ориентируемся на этот вариант)
      • Битрикс24 учитывает только IP-адрес, с которого происходит обращение при выполнении REST-запроса. Ограничение на интенсивность запроса общее для всех клиентов, работающих с одним Битрикс
      • Запрос не равен записи из таблицы. Метод list позволяет получать по 50 записей, а метод batch может содержать 50 запросов по 50 записей

      Ресурсоёмкость:

      • В облачной версии Битрикс24 во всех ответах REST-запросов в массиве time с дополнительной информацией о времени выполнения запроса добавлен дополнительный ключ operating, который говорит о времени выполнения запроса к конкретному методу
      • При превышении общего времени выполнения запросов сверх 480 секунд в рамках прошедших 10 минут данный метод блокируется для всех приложений
      • Все остальные методы продолжают работать

      Исходя из данных ограничений должен быть использован метод batch

      Особенности API

      1. Пагинация по параметру start  указывает смещение в итоговом наборе данных после применения фильтров. Шаг – 50 строк

      2. Если после фильтрации строк меньше 50 (страница), подзапрос с большим start возвращает первую страницу данных повторно – это не ошибка.

      3. Нет возможности заранее узнать точное количество строк после фильтрации.

      4. Batch-запрос содержит до 50 подзапросов.

      5. На один batch-запрос можно получить максимум 2500 строк (50 запросов * 50 строк).

      UI/UX + логика обработки запросов коннектора в системе

      Интерфейс

      Новый тип источника – Bitrix24

Внутреннее окно источника:

  • Название – "Новое подключение"
  • Поле ввода "Название подключения"
  • Поле ввода "URL вебхука"
  • Текст – "Как получить данные для подключения" в виде гиперссылки
  • Кнопка "Назад"
  • Кнопка "Далее"

Все поля обязательны для заполнения

Следующее окно для выбора сущности:

В первой версии для реализации предлагается выгружать все доступные поля из источника (благо на их количество нет никаких ограничений) и производить исключение ненужных столбцов уже в таблице выбора данных на стороне FB

  • Название – "Новое подключение"
  • Текст – "Выберите источник данных в системе"
  • Раскрывающийся список "Источник", содержит в себе значения "CRM", "Задачи", "Бизнес-процессы", "Copilot". По умолчанию стоит "CRM"
  • Раскрывающийся список (без названия), появляется только если в предыдущем списке выбран вариант "CRM", содержит в себе значения "Сделки", "Лиды", "Компании", "Коммерческие предложения", "Смарт-процессы". По умолчанию стоит "Сделки"
  • Чекбокс "Прерывать последовательность запросов в случае ошибки", по умолчанию активен
  • Текст – "Фильтры"
  • Строка фильтрации (следующие компоненты в одну строку):
    • Поле ввода "Поле" (по умолчанию в первое поле должно быть введено "DATE_CREATE")
    • Раскрывающийся список (без названия) со значками:
      • = (по умолчанию)
      • != (в коде "!")
      • >=
      • >
      • <=
      • <
      • LIKE (в коде "%")
      • Поле ввода "Значение"
    • Кнопка "Добавить" (например, "+")
    • Кнопка "Удалить" (можно удалить даже первое условие)
  • Кнопка "Тестовое подключение"
  • Кнопка "Предпросмотр"
  • Кнопка "Создать"
  • Кнопка "Назад"

Все поля обязательны для заполнения (и в фильтре, если строки фильтрации добавлены)

Окно предпросмотра результата:

  • Полностью аналогично окну предпросмотра файла без всех управляющих кнопок:
    • Расположено справа от настроек окна выбора сущности
    • Содержит в себе результат выполнения ограниченного запроса – столбцы с данными

      image.png


Логика

При нажатии на источник "Bitrix24" открывается внутреннее окно источника

Внутреннее окно источника:

  • В поле "Название подключения" вводится название, которое будет отображаться в списке коннекторов и использоваться в скрипте загрузки
  • В поле URL вебхука вставляется готовый URL вебхука из Битрикс24
  • Гиперссылка "Как получить данные для подключения" ведёт на документацию с алгоритмом создания вебхука в Битрикс и получения данных для подключения
  • Кнопка "Назад" возвращает пользователя в окно выбора типа источника
  • Кнопка "Далее" запускает проверку корректности вебхука:
    • Выполняется GET-запрос к указанному URL вебхука с минимальным тестовым запросом (например, получение одной записи или метаданных)
    • Если ответ содержит корректные данные (HTTP 200 и валидный JSON), подключение считается успешным
      • Открывается окно выбора сущности
    • Если ответ содержит ошибку (например, 403, 404 или невалидный формат), отображается сообщение об ошибке с предложением проверить URL

Окно выбора сущности:

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

  • С помощью списка "Источник" выбирается один из методов Битрикс АПИ (см. про каждый метод в разделе "Объекты для выгрузки")
  • Второй раскрывающийся список служит для уточнения метода для CRM (в остальных вариантах пока что доступен только один метод)
  • Чекбокс "Прерывать последовательность запросов в случае ошибки" передаёт в параметр "halt" значение 1 (если чекбокс активен) или 0 (если неактивен)
  • Строка фильтрации формирует условие filter для ограничения данных для поля согласно операнду по значению
    • Все операнды в запросе эквиваленты вариантам из списка для пользователя, за исключением "не равно" (!=) и "как" (LIKE). "Не равно" записывается в формате "!", а "как" в формате "%".
    • Поле нечувствительно к регистру, условие чувствительно к регистру
    • Можно вводить несколько условий: для этого есть кнопка "Добавить" – создаёт ещё одну строку фильтрации со значениями по умолчанию
    • При создании новой строки все элементы модального окна сдвигаются вниз. Когда число таких строк достигает 4, для всех новых строк добавляется прокрутка в окне, а элементы модального окна перестают сдвигаться
      • Пример – окно ввода границ для цвета по значению (после добавления 4 появляется прокрутка)

        image.png


    • Кнопка "Удалить" появляется при наведении курсора на существующую строку. При удалении не спрашивается подтверждение, все последующие строки сдвигаются на одну вверх
  • Кнопка "Создать" отправляет запрос и формирует подключение к Битриксу (новый источник)
    • Если какие-то из параметров указаны неверно (подключение не может сформироваться), то показываем пользователю сообщение: "Не удалось установить подключение. Получена ошибка:" + ответ с ошибкой
  • Кнопка "Назад" возвращает во внутреннее окно источника Битрикс
  • Кнопка "Тестовое подключение" при нажатии отправляет пустой POST-запрос к Битрикс и ожидает ответ без ошибки.
    • Если в ответ приходит ошибка, то показываем сообщение: "Не удалось установить подключение. Получена ошибка:" + ответ с ошибкой
    • Иначе показываем сообщение "Подключение успешно"
  • При нажатии на кнопку "Предпросмотр" отправляется точно такой же запрос, как и при нажатии на кнопку "Создать", но:
    • Устанавливается ограничение (Limit) на 100 строк
    • Источник не создаётся, окно остаётся открытым
    • В случае успеха ответ заменяет предыдущий результат в области предварительного просмотра (справа от настроек)
    • В случае ошибки показываем пользователю сообщение: "Не удалось установить подключение. Получена ошибка:" + ответ с ошибкой
    • До первой успешной попытки предпросмотра область справа будет пустой

Параметр "start" используется только для пагинации при последовательной выгрузке и не поддерживает прямое ограничение по диапазону записей (например, с 458 по 8162)

Формирование запроса (В1)

Данный вариант формирования запросов на 100% проверен и работает, но может быть неоптимален на больших объёмах данных. 

Правила формирования batch-запроса

Для любого метода формируется POST-запрос:

https://<URL_вебхука>/rest/batch

Таким образом вызывается метод batch, который содержит в теле запроса:

  • "halt" – параметр, определяющий, нужно ли прерывать серию запросов в случае ошибки хотя бы в одном из них
  • "cmd" – совокупность подзапросов, из которых состоит batch, с шагом 50 (параметр start)
  • "auth" – параметр авторизации, в него передаётся Access-Токен, полученный при авторизации подключения к конкретному Битриксу

В каждый подзапрос добавляется фильтр согласно параметрам из интерфейса


{
"halt": 0,
"cmd": {
"1": "<МЕТОД>?filter[<ПОЛЕ1>][<ОПЕРАНД1>]=<УСЛОВИЕ1>&filter[<ПОЛЕ2>][<ОПЕРАНД2>]=<УСЛОВИЕ2>...",
"2": "<МЕТОД>?...&start=50",
...
"N": "<МЕТОД>?...&start=(N-1)*50"
},
"auth":"<ТОКЕН>"
}

Пример запроса, в котором:

  • Метод – CRM-Сделки
  • Фильтр: TITLE = 3
  • Две страницы данных

{
"halt": 0,
"cmd": {
"1": "crm.deal.list?filter[TITLE]=3",
"2": "crm.deal.list?filter[TITLE]=3&start=50"
},
"auth":"13fd63680079d1ca0079d1a8000000090000078da0bed620c333479c52eb085a840b8d"
}

Обработка и дозагрузка данных

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

  • Накапливать все полученные строки
  • Отслеживать уникальные значения ID
  • При получении повторяющихся ID считать, что данные закончились – сохранять полученный до повторяющихся ID результат и заканчивать загрузку

Так, единственным флагом для окончания загрузки будет повторение уникальных значений ID. Следовательно, в случае ошибки разработки (например, если одинаковые ID не будут найдены, что по логике невозможно) загрузка зациклится – необходимо учесть этот момент и не допускать ошибок)

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

За один запуск можно отправлять до 50 batch-запросов, поэтому необходимо:

  • Запрашивать batch-запросы последовательно, смещая start в последующих запросах на последний start из предыдущего:
    • При первом вызове отправлять до 50 batch-запросов
    • Каждый новый вызов производить не чаще чем раз в 0,5 сек (см. ограничения API)
    • В каждом новом вызове максимум один batch-запрос
  • Останавливать загрузку, если на очередном batch-запросе не появляется ни одной новой строки

При этом в интерфейсе источник создаётся сразу после нажатия на кнопку "Создать". Формируется новый коннектор в списке со статусом "Занят" до тех пор, пока не завершится дозагрузка данных

Формирование запроса (В2)

Существует более быстрый способ получения больших объёмов данных, который описан в документации Битрикс:

https://apidocs.bitrix24.ru/settings/performance/huge-data.html

Требуется дополнительный ресерч!

Результат

  • Для обоих вариантов результатом загрузки должен являться массив объектов с уникальными записями.

  • Результат сохраняется в БД (аналогично файловому источнику)

Редактирование подключения

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

Все измененные параметры перезаписывают созданное подключение при нажатии на кнопку "Сохранить". Список доступных для изменения параметров аналогичен созданию подключения.

Объекты для выгрузки

Всего в Битрикс24 используется множество различных сущностей, из которых можно получить данные. Для каждой сущности (CRM, Задачи, БП) используется типовой списочный метод, который подставляется в запрос. При создании коннектора можно выбрать одну конкретную сущность.

Список методов:

  • CRM:
    • Сделки – crm.deal.list
    • Лиды – crm.lead.list
    • Контакты – crm.contact.list
    • Компании – crm.company.list
    • Коммерческие предложения – crm.quote.list
    • Смарт-процессы – crm.type.list
  • Задачи – tasks.task.list
  • Бизнес-процессы – bizproc.workflow.instance.list

Многопоточная загрузка

Проблема

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

Цель минимум – ускорить импорт больших файлов (от 1 млн строк) в реализации на Go как минимум в 2 раза по сравнению с загрузкой на node.js

Цель максимум – реализовать загрузку файла объёмом 2+ млрд строк менее чем за 1 час

Бэкенд

Поиск подходящих столбцов – [ЭНДПОИНТ_ПЕРВЫЙ_ПОИСК]

Node.js формирует список задач из SQL-запроса в скрипте загрузки и отправляет их на Go (POST /v1/find-unique-columns). Go-сервис:

  • Парсит все таблицы
  • Оставляет только "простые" (без подзапросов, join, union) – отмечает как "неподходящие"
  • Исключает таблицы, у которых меньше 100 000 записей – отмечает как "неподходящие"
  • Выполняет "исключающий" поиск – определяет столбец который точно подойдёт по метаданным и группировкам:
    • Если столбец является полностью уникальным (задано условие в СУБД), то он подходит
    • Рассматриваются также наборы из нескольких столбцов: набор из всех столбцов, участвующих в группировке, всегда будет уникальным
  • Собирает IndexList из точно подходящих столбцов (Specify = False) и остальных столбцов (Specify = True) и возвращает в node.js

Node.js возвращает список таблиц и столбцов (вместе с их типами данных) на фронт (разделяя подходящие и неподходящие)

Сохранение списка настроек – [ЭНДПОИНТ_СОХРАНЕНИЕ_НАСТРОЕК] 

Для данного проекта записываются все полученные флаги. В запросе на запуск скрипта POST /v1/execute передаются настройки для каждой таблицы:

  • isMultithreading
  • isFullColumnCheck
  • Список столбцов для разделения
  • Запуск скрипта в несколько потоков

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

    • Столбцу, указанному пользователем в настройках 
    • Столбцу, определенному при полном поиске подходящих столбцов

    Если столбец не указан и не найден, то выполняется однопоточная загрузка

    Ручной запуск и запуск по CRON-заданию имеют свои (различающиеся друг от друга) настройки многопоточности! Необходимо для ручного запуска брать свой набор настроек, а для CRON-задания свой (или грузить в один поток, если для CRON-задания не было отдельно настроено правило многопоточной загрузки)


    Фронтенд

    Кнопка "Настройки импорта":

    Расположена:

    • Рядом с кнопками "Сохранить скрипт" и "Запустить скрипт"
    • В настройках CRON-задания в модальном окне, вызываемом при нажатии на кнопку "Обновление данных" в скрипте загрузки
    • В настройках CRON-задания в модальном окне, вызываемом в панели администратора

    Действие:

    • При нажатии на кнопку выполняется проверка скрипта на сохранение:
      • Если скрипт не сохранен появляется модальное окно
        • Название окна: "Управление потоками"
        • Текст:  "Обнаружены несохраненные изменения в скрипте загрузки. Для разделения скрипта на потоки необходимо сохранить все изменения"
        • Кнопка "Сохранить" – при нажатии выполняет стандартный PUT 
          https://fastboard-front-dev.fb-dev.winsolutions.ru/back/api/v1/script, после которого выполняется проверка на существование сохраненных настроек
        • Кнопка "Отменить" – при нажатии возвращает пользователя в скрипт загрузки без сохранения и без открытия следующего окна
      • Если скрипт сохранен, то выполняется проверка на существование сохраненных настроек
    • Проверка на существование сохраненных настроек:

    Пагинация источников в скрипте загрузки 

    Автокомплит в REST API

    Добавить автокомплит в раздел body в REST API.
    Примерный список 
    access_token
    action
    active
    address
    after
    amount
    any
    api_key
    array
    attributes
    aud
    audience
    auth
    authorization
    auto
    avatar
    before
    bigint
    binary
    boolean
    byte
    callback
    captcha
    captcha_token
    category
    channel
    city
    client_id
    client_secret
    code
    code_challenge
    code_challenge_method
    code_verifier
    collection
    comment
    company
    config
    content
    content_type
    context
    country
    created_at
    csrf
    csrf_token
    currency
    customer
    data
    date
    date-time
    datetime
    day
    debug
    decimal
    default
    description
    details
    domain
    double
    double-precision
    dry_run
    duration
    email
    end
    error
    errors
    event
    expires_at
    expires_in
    false
    field
    fields
    file
    filename
    file_size
    filter
    first_name
    float
    float32
    float64
    folder
    format
    from
    full_name
    grant_type
    headers
    host
    icon
    icon_emoji
    id
    id_token
    image
    image_base64
    in
    include
    int
    int32
    int64
    integer
    ip_address
    is_active
    iso8601
    issue
    items
    job
    jwt
    key
    kind
    label
    last_name
    latitude
    limit
    link
    locale
    location
    login
    long
    longitude
    max
    max_length
    message
    metadata
    method
    middle_name
    min
    min_length
    minute
    model
    month
    mutation
    name
    namespace
    nonce
    none
    not_before
    null
    number
    object
    offset
    on
    op
    operation
    operationName
    options
    order
    organization
    page
    page_size
    pagination
    params
    password
    path
    payload
    payment_method
    permissions
    phone
    photo
    platform
    postal_code
    precision
    prefix
    price
    product_id
    profile
    protocol
    provider
    proxy
    public_key
    query
    quantity
    range
    raw
    read_only
    real
    reason
    redirect_uri
    refresh_token
    region
    remember_me
    request_id
    resource
    response_type
    result
    retry
    roles
    root
    route
    rows
    salt
    scope
    scopes
    search
    secret
    secret_key
    send_notification
    serial_number
    server
    session
    settings
    sha256
    signature
    signer
    size
    slug
    sort
    source
    state
    status
    step
    string
    submit
    sub
    subscription
    suffix
    summary
    tag
    tags
    target
    tenant
    text
    theme
    thumbnail
    time
    timestamp
    timezone
    title
    token
    token_type
    topic
    transaction_id
    true
    type
    uint
    uint32
    uint64
    uri
    url
    user
    user_id
    username
    uuid
    valid
    validate_only
    validation_errors
    value
    values
    variables
    variant
    version
    video_chunk
    void
    week
    where
    with
    year
    __typename



    Баги и мелкие фичи

    Выбор типа календаря

    С вводом новой версии календаря, мы теряем компактную версию. 
    Предлагаю добавить в настройки секцию "Тип", по аналогии с круговой
    Image
    В секции будет переключение "Компактный" или "Расширенный" 
    По умолчанию "Компактный" 

    Компактный
    Image
    Расширенный 
    Image

    Создание источника с названием, которое уже используется (поменяй название)

    Проблема

    1. В окне импорта нельзя создать источник, если существует другой источник с данным названием
    2. При попытке выполнить это действие с учётки разработчика, у которого нет доступа к существующим файлам, появляется некорректная ошибка "У вас нет прав читать данный источник" 

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

    Решение

    Расположение: Скрипт загрузки → Создать подключение → Файл

    Триггер Ответственный Действие
    Пользователь ввел текст в поле ввода "Название подключения". Прошла 1 секунда после завершения ввода ФРОНТ

    Выполняем проверку наличия источника с таким же названием на фронте:

    • Если на фронте найден источник с таким же названием, то показываем системное сообщение (ошибку) "Источник с таким именем уже существует"
    • Иначе отправляем запрос на проверку на бэк GET /api/v2/source/check-source-name/{name}
    Пришел запрос на проверку наличия источника GET /api/v2/source/check-source-name/{name} БЭК

    Выполняем проверку наличия источника с таким же названием на бэкенде:

    • Если на бэке найден источник с таким же названием, то передаём на фронт ошибку "Источник с таким именем уже существует, но у Вас недостаточно прав на его просмотр и редактирование"
    • Иначе ничего не возвращаем
    Пришёл ответ с бэкенда с ошибкой "Источник с таким именем уже существует, но у Вас недостаточно прав на его просмотр и редактирование" ФРОНТ Показываем системное сообщение (ошибку) "Источник с таким именем уже существует, но у Вас недостаточно прав на его просмотр и редактирование"
    Пользователь нажал кнопку "Создать" ФРОНТ

    Выполняем проверку наличия источника с таким же названием на фронте:

    • Если на фронте найден источник с таким же названием, то показываем системное сообщение (ошибку) "Источник с таким именем уже существует"
    • Иначе отправляем запрос на создание источника POST /api/v2/source
    Пришёл запрос на создание источника POST /api/v2/source БЭК

    Выполняем проверку наличия источника с таким же названием на бэкенде:

    • Если на бэке найден источник с таким же названием, то передаём на фронт ошибку "Источник с таким именем уже существует, но у Вас недостаточно прав на его просмотр и редактирование"
    • Иначе создаём источник

    НЕ ВНЕСЛА:

    Объединение запросов по get_data (+SSE на node.js)