Руководство разработчика Интеграл
Задача Интеграла – избавить пользователя от необходимости прикладного программирования. Это среда разработки приложений, а сама разработка сводится к постановке задачи – пользователь описывает модель данных, правила их обработки и формат выдачи результатов. Конструктор прост, в нем реализованы только основные возможности, но он постоянно развивается, чтобы стать более понятным и дружественным к пользователю.

С базовыми функциями Интеграла вы можете ознакомиться здесь.

Регистрация, установка и состав системы
Установка и выбор шаблона для Интеграла здесь: https://winne.ru/register.html
После установки вы получаете доступ к собственной базе, в которой уже существуют такие объекты как Пользователь, Роль, Запрос, имеющие свой набор реквизитов. Интеграл знает, как обращаться с этими объектами – Роль пользователя определяет уровни доступа ко всем объектам базы, Запрос выбирает данные из базы и так далее. Предустановленные объекты необходимы в любом приложении, а вот всему остальному вы научите Интеграл самостоятельно.
Пользователь, созданный при регистрации вместе с базой, имеет имя, совпадающее с именем базы, и права администратора в системе.


Архитектура приложения Интеграл
Система состоит из пяти универсальных форм и меню работы с файловой системой:
1. Форма редактирования типов (меню Типы)
2. Словарь (справочник) типов объектов (меню Словарь)
3. Список объектов выбранного типа (любого значения в меню Словарь)
4. Форма редактирования объектов
5. Форма отчета
6. Администратор директорий, где можно загружать шаблоны страниц
Модель данных доступна вам через меню «Типы», список всех независимых типов (тех, что не являются реквизитами других типов) находится в меню «Словарь».

Часть функционала шаблона может быть сделана при помощи пользовательских html–форм и отчетов. Список html и css файлов находится в меню «Файлы» в директории templates. В директории download меню «Файлы» хранятся файлы, загруженные пользователями базы данных.

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

Основной принцип Интеграла: его программист не обязан знать язык программирования или теорию баз данных, а максимальная требуемая квалификация не превышает уровень пользователя MS Excel. Интеграл позволяет решать любую задачу, оперируя только терминами бизнеса и не неся никаких накладных расходов при постановке задачи и ее выполнении.
Разумеется, самыми примитивными функциями уровня Excel (СУММА, СРЕДНЕЕ и т.п.) познакомиться, вероятнее всего, понадобится, что не противоречит озвученному выше принципу. Также будет очень полезно знать список служебных слов Интеграла и правила их использования.

Значительная часть функционала Интеграла построена средствами самого Интеграла, это Пользователи, Роли пользователей, Объекты доступа и Отчеты. Вы можете использовать и дополнять соответствующие сущности, исходя из ваших нужд, но при этом следует соблюдать осторожность. Категорически не рекомендуется удалять перечисленные типы или их реквизиты.

Модель данных
В вашем распоряжении модель данных, состоящая из связанных между собой таблиц. Вы определяете термины, такие как Клиент, Счет, Договор, Телефон, Встреча, Категория, а затем указываете связи между соответствующими объектами. С помощью этих связей система самостоятельно агрегирует данные для навигации в системе и при построении отчетов. Система позволяет создать любую иерархию данных, подобно реляционной базе данных.
Например:
· Клиент имеет реквизит Телефон (подчиненный реквизит Телефон);
· Клиент имеет списочный реквизит Категория (подчиненный реквизит, ссылающийся на значение из справочника Категорий);
· Для Клиента хранится информация обо всех проведенных с ним Встречах (подчиненный массив Встречи);
· Договор имеет ссылку на Клиента, с которым он заключен (Один клиент — много Договоров).
Структура базы данных для описанного выше примера:

Редактор типов Интеграла
Редактор типов находится в меню Типы. Вы обнаружите, что в Редакторе типов уже зарегистрировано какое-то множество объектов, потому что Интеграл написан, по большей части, средствами самого Интеграла, что позволяет вам дописывать и переписывать его под себя.
Объекты в Редакторе типов расположены в порядке связанности или подчиненности, при этом каждый объект встречается только один раз — нарисован в иерархии при первом упоминании в качестве реквизита.
Все термины (Типы), используемые системой, создаются здесь (см. Новый тип –> Создать Тип на рисунке). Вы задаете название Типа данных и указываете для него базовый тип данных:
Базовый тип сообщает системе, как выводить и обрабатывать соответствующие значения.
Для добавления типов в Интеграл необходимо задать имя нового типа, выбрать ему базовый тип и нажать «Создать тип». Для примера создадим тип «Клиент»:
Как только вы добавили термин, в меню Словарь появляется соответствующий пункт, и вы сразу же можете заносить в систему объекты этого типа. Попробуйте:
Аналогичным образом создаются все остальные термины (типы): Счет, Договор, Телефон, Встреча, Категория. После этого можно подчинять одни типы другим, создавая сущности произвольного состава: выбираем тип из списка, кликнув его имя, и нажимаем «Добавить реквизит».
Все изменения в Редакторе типов немедленно вступают в силу и отображаются в Словаре.
Если какой то тип планируется использовать в качестве справочного значения, то необходимо создать ссылку на этот тип, которая затем будет использоваться в качестве реквизита. Например, добавим ссылку на тип Категория:
В списке типов появится новый тип с префиксом ссылки: «-> Категория».
А теперь добавим соответствующий реквизит клиенту:
Во время редактирования такого реквизита можно выбрать значение из списка:
Реквизиты можно добавлять, удалять (знак «Х» напротив реквизита) и изменять их порядок (нажатие на знак «^» перемещает реквизит на одну позицию выше).
Описание рассмотренной выше структуры данных в Редакторе типов Интеграла выглядит так:
Последовательность реквизитов в Редакторе определяет их последовательность и в таблицах системы:
В первой колонке таблицы содержится значение объекта, в остальных – его реквизиты. Значение также всегда имеет уникальный системный идентификатор (цифровой, выделен на рисунке красным):
Обычному пользователю этот идентификатор, вероятнее всего, никогда не понадобится. Однако, как мы увидим позже, знание о нем может пригодиться аналитику при настройке системы.
Обратите внимание, что если реквизит сам имеет реквизиты, то он отображается в виде массива данных, то есть позволяет задать не одно, а несколько значений (см. реквизит Встречи типа Клиент). Такой подход в некоторых случаях может значительно упростить навигацию в системе.

Справочники
Все данные представлены в Интеграле в виде таблиц. Таблица Категория:
Таблица Клиент с реквизитами Телефон, Категория (из списка категорий), Встречи (массив):
Нажав на значение в колонке «Встречи» можно посмотреть связанный массив данных по встречам этого клиента:
Список договоров в системе содержит ссылки на клиентов, с которыми заключен договор:

Валидация(проверка значений) данных
Одно из простейших средств для проверки данных при вводе – это реквизит, обязательный для заполнения. Вы можете указать его в Редакторе типов, нажав на квадратные скобки напротив выбранного реквизита (в квадратных скобках появится знак «!»):
При попытке сохранить неверно заполненную форму система выведет предупреждение и оставит пользователя в режиме редактирования формы:
Вычисляемые реквизиты
Поле «Значение по умолчанию» можно также использовать для автоматического заполнения значений реквизитов при создании объекта: то, что вы впишете в это поле, попадет в соответствующее поле формы редактирования при создании новой записи. В этом поле также можно использовать служебные слова.
Для ссылочных реквизитов («--> Клиент», «--> Категория») следует указывать не имя Клиента или название Категории, а их внутренний идентификатор (ID): система хранит ссылки на ID (имя может быть изменено, а идентификатор – нет). Например, если мы хотим по умолчанию присваивать клиенту категорию «Лид», то нам нужно прописать для поля «--> Категория» значение его ID:
Не забудьте нажать кнопку «Сохранить» или Enter после редактирования каждого поля!
Теперь при создании клиента система сама проставит ему Категорию «Лид», причем пользователь сможет изменить это значение на любое другое.
Если объект с идентификатором, вычисленным по умолчанию, не соответствует типу реквизита, то его значение не будет использовано и не будет сохранено в базу формой редактирования объекта.

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

Поиск и редактирование
По умолчанию в таблицах системы отображаются только первые 20 записей, а поиск объектов осуществляется с помощью фильтров в заголовке таблицы. Поля фильтра открываются по клику на шапке таблицы объектов или по нажатию иконки «воронка» над шапкой таблицы. Фильтр может быть диапазонным, если это потенциально применимо (для дат и чисел), или по маске.

Типичные способы задания фильтров показаны на рисунке:
Обратите внимание на конструкцию !% («не непустой», в противоположность %). Эта конструкция одинаково работает и в списках, и в отчетах. Вообще, модификатор «!», используемый в начале строки условия, обозначает отрицание последующего условия, например, !%подар% будет означать «всё, что не содержит 'подар', включая пустые (отсутствующие) значения».

Обратите внимание, что при задании даты в текущем месяце текущего года можно указать только число. Например, если сегодня 31.08.2016, то:
12 – 12-е число текущего месяца: 12.08.2016
12.6 – 12 июня текущего года: 12.06.2016
При указании года двумя цифрами, например 12.12.16, система сохранит год в текущем веке: 12.12.2016. Если необходимо указать год в другом веке, то его нужно указывать целиком: 12.12.1916.
В качестве разделителя дат можно использовать символы «.», «,» или «/».

Чтобы отредактировать запись, нужно нажать на значение в ее первой колонке:
Удалить запись можно нажатием кнопки «Удалить», при этом Интеграл запросит подтверждение на удаление. Если на запись есть ссылки в системе (например, это списочное значение, использующееся в объектах Интеграла), то система выдаст предупреждение и не позволит удалить эту запись.

Если в выпадающем списке какой–то формы более 50 записей, то в списке присутствуют только первые 50 из них, и тогда для поиска записей нужно использовать поле справа от списка:
Для поиска по различным полям выпадающего списка следует разделять маски поиска знаком «слэш», например, для поиска записей со словом «cherie» во второй колонке нужно использовать условие поиска: /%cherie% (или %/%cherie%):
Если у пользователя есть доступ для создания объектов используемого списочного значения, например, Товар на рисунке выше, то слева от списка будет изображена кнопка немедленного добавления списочного значения (со знаком «+»). По этой кнопке можно задать новое значение, которое будет добавлено в список при сохранении формы:
Система позволяет сделать копию любого объекта вместе со всеми его реквизитами, включая массивы. Для этого нужно открыть объект, при необходимости внести изменения и нажать кнопку «Копия».

При добавлении записей в подчиненный массив данных они сохраняются в порядке добавления. Записи можно удалять (значок «Х») или перемещать (значок «^» перемещает запись на одну позицию вверх):

Экспорт и импорт данных
Пользователь может экспортировать структуры данных и сами данные, а затем импортировать их в другую базу Интеграла или использовать по другому назначению. Также возможна подготовка данных из сторонних систем для загрузки их в Интеграл.
Формат выгрузки содержит необходимый минимум информации, начиная с описания типа, для которого делается выгрузка.
Описание типов (после описания каждого типа идет описание подчиненных и связанных типов):
ID_типа:имя_типа:базовый_тип_типа;[имя_реквизита:базовый_тип_реквизита; | ID_типа_ссылочного_реквизита;, ...]
Описание данных:
ID_типа_записи:[ID_записи];значение_записи;[реквизит;, ...]
Для экспорта необходимо зайти в нужный вам справочник, отфильтровать данные, если требуется, и нажать кнопку «Экспорт BKI». Будет выгружен файл, содержащий:
1. Описание структуры данных, включая все подчиненные данные и связанные справочники
2. Сами данные (на рисунке ниже данные начинаются с выделенной серым строки)

Таким образом вы можете:
-экспортировать ваши наработки, например, если вы хотите продать разработанные вами шаблоны новому клиенту;
- экспортировать и импортировать справочники, включая иерархические структуры любой вложенности;
-импортировать подчиненные массивы данных для выбранного объекта (например, историю встреч клиента).
Интеграл корректно разрешит ситуацию, если в целевой системе уже есть нужные вам типы данных: они будут найдены по комбинации «Тип:базовый тип» и использованы в качестве терминов или их реквизитов.

Интеграл разрешит проблемы с конфликтующими ID в целевой системе, но прекратит импорт, если реквизит с данным номером уже занят, и существующий реквизит имеет имя и тип, отличные от загружаемого. Например, Интеграл сообщит об ошибке, если вы импортируете Клиентов с двумя реквизитами Имя (SHORT) и Телефон (SHORT), а в целевой базе Клиент имеет реквизит Имя с типом CHARS или эти реквизиты имеют другой порядок или названия (например, «Тел.» вместо «Телефон»). Если же все имеющиеся реквизиты совпадают, но вы импортируете какие-то дополнительные, то они будут добавлены к описанию Типа в целевой системе. Например, вы можете выгрузить Клиентов с указанием Имени и Телефона, добавить в выбранный файл третий реквизит Категория, указать значение этого реквизита для всех клиентов и загрузить всё это обратно в Интеграл (предварительно удалив выгруженных клиентов из справочника!).

Если выгружаемые значения могут быть использованы как справочные (в Справочнике типов есть реквизит ссылки на этот Тип, например, «--> Товар»), то данные будут выгружены вместе с идентификаторами. В противном случае идентификаторы выгружены не будут, поскольку не имеют критичного значения.

Если в каких-то полях данных встретятся переводы строки или точки с запятой (служащие разделителями в файле), то Интеграл с этим легко справится и корректно загрузит данные, экранировав точки с запятой и контролируя количество полей данных.

Если в загружаемом файле указаны ID записей, то Интеграл не будет заменять уже имеющиеся записи с такими ID, значением и типом, не проверяя соответствие остальных реквизитов. Если ID занят, а тип и значение не совпадают, то Интеграл прекратит импорт, сообщив о конфликте (ID занят объектом с другим значением или типом).

Формат выгрузки или загрузки для простейшего справочника, который можно выгрузить из Интеграла или подготовить вручную приведен на рисунке:


Запросы (отчеты)
Построитель отчетов Интеграла позволяет конструировать отчет, просто выбирая нужные пользователю колонки и не заботясь о том, как связать таблицы, участвующие в построении отчета.
Построитель отчетов позволяет реализовать любую конструкцию языка SQL, включая вложенные запросы. При этом сам язык SQL знать не обязательно.
Допустим, нам требуется выбрать всех клиентов, с которыми были подписаны договоры и прошли встречи в этом месяце, в формате:
Клиент-Категория-Телефон-Дата-Тема встречи
Также нужно подсчитать общее количество таких встреч.
Такой отчет потребует выборки данных из 4 таблиц системы, но это нас нисколько не заботит.
Заходим в меню Словарь –> Отчет и добавляем нужный нам отчет:

Заходим в массив Колонки отчета (см. красный овал справа на предыдущем рисунке) и добавляем колонку «Клиент»:
На открывшейся форме выбираем «COUNT» в выпадающем списке «Итог» и нажимаем «Сохранить»:
Графа «Итог» служит для указания функции, которую нужно вывести в итоговой строке отчета по этому полю: AVG (среднее), COUNT (количество), MAX (максимальное), MIN (минимальное), SUM (сумма).
После того, как мы добавили первую колонку отчета, выпадающий список «Колонки отчета» сократился до тех значений, которые имеют связь с таблицей клиентов:
Добавляем колонку «Клиент –> Категория», правим поле Имя в отчете на «Категория» и сохраняем:
Теперь в нашем отчете уже 2 колонки, и мы добавляем третью: «Договор». Сама по себе эта колонка в отчете не нужна, но у нас есть условие, что клиент должен попасть в отчет, только если у нас с ним есть договор. Здесь мы задаем условие, что поле «Договор» не должно быть пустым. В полях «Значение (от)» и «Значение (до)» используются те же правила, что рассмотрены в Поиск и редактирование:
Обратите внимание на поставленную галку «Скрыть»: эта колонка не будет отображена в отчете.

Аналогичным образом добавляем остальные колонки в отчет, не забыв указать условия по дате встречи: с 1 по сегодняшнее число текущего месяца (см. колонку «Встречи»):
Все эти действия заняли у нас не больше 2 минут, и теперь по кнопке «Сформировать» на форме отчета мы получим такой отчет, построенный точно по нашему заданию:

Агрегирование в отчетах
Также в отчете можно применять агрегирующие функции: сумма, количество, минимальное, максимальное, среднее. В следующем примере создан отчет, который выводит количество встреч с клиентами с указанием периода, в который эти встречи прошли:
Отчет отсортирован сначала по категории клиента, затем по его имени. Также, для удобства восприятия, формат даты приведен к виду DATE (дата), вместо DATETIME (дата и время):

Интерактивные отчеты
Если в отчете выставлена опция «Интерактивный», то объекты в этом отчете отображаются гиперссылками, по которым можно попасть на форму просмотра и редактирования этого объекта:

Фильтрование данных в отчете и экспорт в MS Excel
Интеграл позволяет применять фильтры к данным в уже построенном отчете, при этом отчет будет перезапрошен с сервера, чтобы удовлетворять заданным условиям. Фильтр открывается по клику на шапке отчета или иконке «воронка» справа вверху отчета. Фильтр сработает на тех полях, у которых задано «Имя в отчете», это сделано из соображений безопасности – чтобы пользователь не мог отменить фильтры, наложенные разработчиком отчета на такие поля.

Сформированный отчет можно выгрузить в MS Excel соответствующей кнопкой.

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

Добавим в Редакторе типов новый тип Менеджер и ссылку на него:
Добавим наших менеджеров в таблицу (Словарь –> Менеджер):
Затем добавим ссылку на менеджера в таблицы Пользователь и Клиент в Редакторе типов:
Теперь мы можем указать для каждого пользователя, какой менеджер под ним работает:
Далее мы сделаем отчет (назовем его «ID_менеджера»), который позволит нам вычислить менеджера по имени пользователя:
Здесь мы используем фильтр для поля пользователь: служебное слово [USER], а также служебную функцию abn_ID, чтобы преобразовать имя менеджера в его идентификатор (список служебных слов смотрите в разделе Служебные слова и функции).

Когда мы запустим этот отчет, то увидим в нем единственную строку с идентификатором менеджера Мария (182053), привязанного нами ранее к пользователю manual:
В поле «Значение по умолчанию» реквизита «--> Менеджер» (ссылка на менеджера) типа Клиент проставим имя нашего отчета: ID_менеджера.
Теперь Интеграл будет знать, что при создании нового Клиента нужно запустить отчет ID_менеджера и подставить полученное в нем значение в поле Менеджер:

Колонки отчета: подробнее
Рассмотрим подробнее назначение полей Колонки отчета:
Имя в отчете – название колонки в выводимом отчете, по умолчанию – значение Колонки отчета.
Формула задает вычисляемое выражение или псевдоним колонки. В выпадающем списке колонок отчета на последней позиции находится значение «Вычисляемое». Это синтетическое поле, которое позволяет вставить произвольные операторы и функции, допустимые в языке SQL. При этом можно оперировать любыми другими колонками отчета, если для них задан псевдоним в их поле Формула.

Например, следующий отчет вычисляет название месяца на английском из даты встречи (в базе она хранится в секундах с 01-01-1970 00:00:00) и преобразует имя клиента в заглавные буквы:
Отчет при этом будет выглядеть так:
Вряд ли вы будете часто использовать подобные возможности, но вы должны знать, что Интеграл предоставляет доступ к очень мощным и гибким средствам для различных вычислений.
Если в поле Формула встречается выражение в квадратных скобках, то система попытается найти соответствующий отчет и использовать данные из него (см. Использование вложенных запросов в отчете).

Значение (от), Значение (до) – диапазон значений (для дат и чисел) или маска (для текста). Здесь работают правила фильтрования из раздела Поиск и редактирование и можно использовать служебные слова. Также здесь можно использовать значение других полей отчета, если заключить их имя из колонки Формула в квадратные скобки.
Функция – агрегирующая функция, применяемая к значению поля: AVG (среднее), COUNT (количество), MAX (максимальное), MIN (минимальное), SUM (сумма). Группировка значений, посчитанных этой функцией, происходит по всем полям, в которых не используется агрегирование (не указана одна из перечисленных функций): в рассмотренном выше отчете «Встречи по клиента» группировка осуществляется для всех комбинаций Клиент – Категория.
Функция (от), Функция (до) – диапазон значений (для дат и чисел) или маска (для текста), применяемые после вычисления функций, указанных в поле Функция (аналог ключа HAVING в SQL). Здесь также работают правила фильтрования из раздела Поиск и редактирование и можно использовать служебные слова. Также здесь можно использовать значение других полей отчета, если заключить их имя из колонки Формула в квадратные скобки.
Скрыть – если поставить галку в этом поле, то соответствующая колонка не будет отображена в отчете, хотя ее значение может использоваться для вычислений, фильтрования и сортировки отчета.
Формат – конечный формат отображения поля. Служит для приведения значения к нужному виду. При использовании формата HTML теги языка HTML не экранируются, как это делается со всеми остальными типами данных для исключения внедрения и исполнения произвольного javascript на страницах браузера.
Сорт. – указатель последовательности и направления сортировки отчета. Отрицательное число здесь даст обратную сортировку (по убыванию значений).
Итог – агрегирующая функция, применяемая к значениям колонки отчета. Если указана функция хотя бы в одной колонке, то в отчете выводится итоговая строка с соответствующими значениями.

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

В 9-ой строке Колонок отчета используется вызов отчета PAID_TILL, который в качестве условия отбора использует номер карты CARD_NO исходного отчета: отчет PAID_TILL выберет максимальную дату, до которой оплачена услуга по заданной карте.
Еще один пример использования вложенных отчетов в поле Формула: данные собираются из трех дополнительных отчетов Daily_bar, Daily_purchase и Daily_replenish. Подобные решения применяются, например, при расчете оборотно–сальдовой ведомости.

Вызов отчета с произвольными параметрами
Пользователь может передать в отчет свои параметры для фильтрации данных.

Например, есть такой отчет:
Он выводит следующую информацию:
Обратите внимание на параметры в строке адреса: FR_MANAGER=Света&FR_DATE=09/09/2016
Эти параметры позволяют передать в отчет произвольные фильтры, которые будут применены построителем отчета. Правила таковы: для фильтра «Значение (от)» колонки отчета MANAGER следует передать в отчет FR_MANAGER=значение; для фильтра «Значение (до)» используется конструкция TO_MANAGER=значение. Фильтр можно применить только к тем колонкам, для которых задано «Имя в отчете».

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

Запросы на изменение данных
Интеграл позволяет массово изменять данные, в том числе находящиеся в разных таблицах. Запрос на изменение можно добавить к любому отчету – необходимо указать новые значения колонок, отобранных в отчете. Таким запросом можно удалять объекты и их реквизиты, а также создавать новые записи, подчиненные или связанные с выбранными в отчете объектами.
Изменение данных происходит в 2 этапа. Сначала формируется отчет, в котором указаны какие данные будут изменены и как, после чего пользователь дает команду выполнить эти изменения, и они выполняются.

Рассмотрим такой пример: нам необходимо отобрать всех Клиентов, с кем первая встреча была осенью 2016 года, и указать в Примечании Клиента «Осень 2016». Отчет, выполняющий эту работу, будет выглядеть так (обратите внимание на графу «Присвоить»):
Результат работы отчета будет следующим:
В графе Присвоить указано, какие изменения будут внесены в данные. При нажатии гиперссылки «Выполнить» отчет сформируется еще раз, и все изменения будут применены. Отчет при этом будет отображать данные какими они были до внесения изменений:
Но в таблице Клиентов мы увидим обновленные данные:
Обратите внимание, что в построителе отчетов присваиваемое значение заключено в кавычки, в отличие от полей Значение (от и до) и Функция (от и до). Поле «Присвоить» может использовать значения поля «Формула», а также функции языка SQL для вычисления присваиваемого значения. Для демонстрации этих возможностей на примере усложним задачу – будем не заменять Примечание Клиента, а дописывать к нему текст в конце с указанием номера телефона. Доработаем наш отчет следующим образом:
Теперь мы не будем терять информацию из Примечания, а просто дополним её:
У вас может возникнуть вопрос: что будет, если какой-то объект встречается в отчете больше одного раза, и мы пытаемся его изменить. Ответ: объект будет изменен только 1 раз. Например, в следующем отчете мы добавляем Примечание клиента, который упомянут в нескольких строках отчета, и Интеграл выполнит изменение только 1 раз для каждого клиента:
Теперь продемонстрируем создание новых записей. Пример: нам нужно запланировать на 1 ноября 2016 года встречи со всеми клиентами в статусе «Лид». Создадим такой отчет:
Внимание! Если в колонке отчета заданы условия отбора и заполнено поле Присвоить, то Интеграл трактует условие отбора как заданное условием или пустое. Таким образом можно убедиться, что будет создано только одно новое значение и предотвратить создание дубликатов при многократном запуске отчета.
Этот отчет выдаст нам следующее:
Как следует из отчета, у этих клиентов пока нет встреч на 1.11.2015, но Интеграл добавит им соответствующие записи, когда мы нажмем «Выполнить»:
Зайдём во Встречи одного из этих клиентов и убедимся, что нужная запись создана:
Если мы запустим этот отчет снова, то он уже не добавит еще раз эти записи, но исправит Тему встречи, если она будет отличаться от заданной (например, мы заменили Интеграл на CRM):
В следующем примере мы удалим информацию обо всех встречах сентября 2016 года:
Для удаления записей используется пустое значение: "". Интеграл не тратит память на пустые значения, поэтому информация будет просто удалена:
При нажатии кнопки «Выполнить» все эти записи будут удалены, включая все подчиненные им реквизиты (в том числе массивы).

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


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

Запросы на изменение Интеграла – это очень мощный инструмент, не имеющий аналогов в других системах хранения и управления данными.

В строке адреса отчета, выполняющего изменения, можно наблюдать флаг «confirmed» – этот флаг сообщает Интегралу, что изменения подтверждены пользователем и должны быть немедленно выполнены. Вы можете использовать это знание для генерации ссылок на страницах интерфейса пользователя, чтобы выполнять изменения без подтверждения: по ссылке будет запущен отчет, который сразу выполнит запрошенные изменения.

Аналог ключа LIMIT в отчетах Интеграла
Пользователь может задать максимальное количество возвращаемых отчетом записей и смещение, начиная с которого необходимо выбирать записи: аналог ключа LIMIT в языке SQL. Соответствующий параметр отчета называется «Вернуть не более» и он может принимать пару значений, разделенный запятой, аналогично LIMIT. Этот параметр также можно передать запросом POST или GET при вызове отчета.

Следующий отчет вернет не более 10 записей:
Будучи вызван с параметром LIMIT, задающим количество строк и смещение, вернет требуемое количество записей (8) с заданной страницы отчета (15), позволяя таким образом листать отчет:
Количество записей на страницы, переданное параметром запроса, не может превышать заданное в отчете из соображений безопасности.

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

Использование запросов к внешним источникам
Интеграл позволяет обратиться к внешним системам (сайты, API, файлы и т.д.) по протоколу http во время выполнения отчета. Для этого необходимо задать шаблон URL внешнего источника в поле URL отчета. В шаблоне можно использовать значения полей отчета, заключив их имена в квадратные скобки (см. [phone], [name]):
Далее при выборе колонок отчета можно задать их имена, и значения этих колонок будут подставлены в шаблон для каждой строки отчета:
Функция abn_URL заменит содержимое своего поля на результат выполнения запроса к полученному URL. В результате выполнения, например, заданного выше запроса к API поставщика SMS-сервиса мы получим ответ сервиса с идентификатором отправленного сообщения, которое придет на заданный нами телефон [phone] получателю с именем [name]:
Результат запроса к URL можно также сохранить в базе, присвоив его значение какому-либо полю, в том числе с использованием флага confirmed.

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

Реквизит типа Кнопка (BUTTON)
Среди базовых типов данных есть особый тип – BUTTON. Реквизит этого типа отображается на форме редактирования объекта в виде «кнопки» – это некое действие с редактируемым объектом. Эта кнопка вызывает пользовательскую html–форму и передает ей в качестве параметра идентификатор текущего объекта. Для пользовательской формы можно настроить отчет, получив тем самым любое рабочее место для операций над текущим объектом и любыми связанными данными.
Интеграл заменит значения [ID] и [VAL] соответственно на идентификатор и значение родительского элемента, в данном случае Товара: ID=183755 и VAL=1240000214642.

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

Разграничение прав пользователей
Интеграл поддерживает разграничение прав пользователей при помощи ролей доступа с детализацией до отдельных полей и их значений. Список пользователей находится в меню Словарь –> Пользователь. Имя пользователя, работающего в системе в данный момент, отображено в нижнем левом углу каждой страницы (см. рисунок ниже). Для каждого пользователя задана Роль:
Кликнув название роли пользователя, можно просмотреть детали этой роли и заданные ей объекты:
На рисунке показаны все разрешенные для просмотра и редактирования типы объектов, а также видно, что колонка «Закупка» (цена закупки товара) в таблице партия будет скрыта от пользователя с ролью User. Кроме того, отчеты, доступные только для чтения, ограничены маской « %», то есть пользователь увидит только те отчеты, название которых начинается с двух пробелов.

Уровни доступа Интеграла заданы в справочнике Словарь –> Доступ:
На уровне Роли Интеграл позволяет разрешить или запретить доступ пользователей к функциям экспорта и массового удаления данных определенный типов:

Пользовательские файлы
Меню Файлы в интеграле доступны только пользователю с именем, совпадающим с именем базы, и пользователю с именем admin.

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

У каждого файла есть системный идентификатор, из которого вычисляется имя папки и имя файла: имя файла – это последние 3 цифры идентификатора + шифр из 8 цифр; имя папки – это остальные цифры идентификатора + шифр из 8 цифр. На следующем рисунке показано, как будет храниться файл с идентификатором 104081 и расширением jpg:
Зная идентификатор файла, вы можете визуально найти его среди остальных. Вы можете скачивать файлы на свой компьютер, а также загружать их на сервер, при необходимости перезаписывая существующие файлы.

Обратите внимание, что файлы сохраняются в зашифрованных папках только будучи загружены через форму редактирования объекта – edit_obj (см. формы), то есть при нормальной работе пользователей Интеграла). Если администратор загрузит файл через меню Файлы, то он будет загружен как есть. Поэтому если вы загружаете в эту папку актуальные версии руководства пользователя и/или служебных инструкций, то рекомендуется использовать секретное (хешированное) имя файла.

Генерация web–страниц Интеграла
Базовый интерфейс Интеграла построен на пяти универсальных формах по единому принципу: html–шаблон содержит точки вставки информации из системных отчетов. Все эти формы, кроме отчета, вставляются в главную форму main.html, шаблон которой доступен для редактирования администратору. Администратор также может создавать свои html–формы и использовать их как внутри главной формы, так и самостоятельно.

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

Адрес страницы выглядит так:
https://tryjob.ru/{db}/{object}/{id}
где синим цветом выделены параметры:
db – имя базы данных;
object – имя универсальной формы;
id – идентификатор объекта, над которым производится действие.

Например, адрес для редактирования (форма edit_obj) объекта с id=776 в базе test будет:
https:// tryjob.ru/test/edit_obj/776

Задача аналитика при разработке html–формы: правильно подготовить и передать параметры для ее отображения. На данном этапе дорабатывается спецификация для более простого и быстрого создания собственного функционала, и вскоре она будет опубликована.


Пользовательские html–формы и блоки данных
Все пользовательские html–формы находятся в меню Файлы, в директории templates:
В коде форм встречаются объявления блоков данных – это кубики, из которых собирается Интеграл:
<!-- Begin: Store --> … <!-- End: Store --> и <!-- File: a -->
Эти конструкции обозначают блоки для вставки информации из отчетов. При построении страницы Интеграл заполняет точки вставки, заключенные в фигурные скобки {...} в блоках данных, пока у него не закончатся данные.

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

Есть две полезные конструкции для обращения к значениям родительского блока и значениям, переданным запросом POST или GET, а также сохраненными в cookie:
Встретив выражение {_parent_.GOOD_ID}, Интеграл будет просматривать все родительские блоки, пока не обнаружит первое значение GOOD_ID.
Конструкция {_request_.GOOD_ID} проверит наличие параметра GOOD_ID, переданного с запросом, и будет использовать его значение, если таковое задано.
Блоки данных – третий важнейший элемент, помимо отчетов и типов. Принцип работы Интеграла очень прост: берем шаблон, смотрим, какие там блоки, ищем соответствующие отчеты и заполняем блоки данными.

Некоторые отчеты являются служебными, например, для блока &Top_Menu в главной форме Интеграла, представленной на следующем рисунке. Служебные отчеты начинаются с амперсанда «&», их не видно среди других отчетов Интеграла и нельзя редактировать.

Конструкция <!-- File: a --> означает, что будет найден файл, имя которого содержится в переменной a, переданной с запросом POST или GET, и этот файл будет вставлен вместо этой конструкции. При этом в этом файле могут содержаться точки вставки данных и другие файлы, что будет также обработано Интегралом и заполнено данными.

Внимание! Имя файла должно передаваться без указания расширения html.

Рассмотрим пример создания пользовательской формы для оперативного просмотра остатков на складе (пользовательское меню Склад). Форма склада будет вложена в главную страницу системы main.html при помощи только что рассмотренной конструкции File. На этой форме пользователь может искать товар по нескольким параметрам, по умолчанию – по штрих–коду:
Файл формы Склада в директории templates – store.html, а его код представлен на следующем рисунке.

Форма состоит, в частности, из элемента html <form> – форма, которая вызывает сама себя (см. action="/{_global_.z}/store") и передает введенные параметры: Штрих-код (FR_CODE), Марка (FR_FIRM) и другие. Эти параметры будут использованы в отчете, как описано в разделе Вызов отчета с произвольными параметрами.

блок Store не является служебным, поэтому Интеграл попытается найти соответствующий отчет в справочнике отчетов, выполнить его, а из его колонок заполнить точки вставки в блоке Store: {DATE}, {FIRM} и остальные. Сколько строк вернет отчет Store, столько раз повторится на странице кусок html–кода между тегами <!-- Begin: Store --> и <!-- End: Store -->, а значения из отчета попадут в соответствующие точки вставки.
По умолчанию при открытии этой формы фокус попадет в поле штрих–код (оно помечено «autofocus»), и если при этом пользователь введет код и нажмет Enter или отсканирует код сканером, то форма вызовет сама себя с параметром FR_CODE, который применится в виде фильтра по полю CODE в отчете Store (см. выделенное красными прямоугольниками на рисунке).
На приведенном выше рисунке меню Склад был отсканирован код 8697923495536, для которого отчет вернул одну запись, и эта запись была в итоге отражена в таблице на форме Склада.
Несколько моментов, на которые нужно обратить внимание:
блоки, обозначенные зеленым цветом в html–коде, являются вложенными: info содержит Store, который, в свою очередь, содержит блок MyBar;
из блока MyBar мы можем обратиться к вышестоящему блоку и запросить у него данные – идентификатор товара GOOD_ID, для чего используем {_parent_.GOOD_ID};
при отправке формы на сервер интеграла следует использовать адрес /{_global_.z}/store, где store – имя вызываемой формы;
{_global_.z} – внутренняя глобальная константа Интеграла, содержащая имя базы;
блок MyBar – это гиперссылка не некое действие (продажа товара из этой конкретной строки), это действие создает объект «продажа», для чего содержит команду ;
вы можете сообщить Интегралу, какую форму открыть после того, как он выполнит заданное вами действие (например, создание «продажи», запущенное из блока MyBar);
создавая произвольные формы (рабочие места) и направляя пользователя от одной из них к другой, вы можете моделировать бизнес–процессы любой сложности.

Интеграл также понимает конструкцию <!--Elapsed-->, которая будет заменена информацией об имени пользователя, количестве запросов к базе для построения этой страницы, времени выполнения запросов, полном времени построения страницы и временном сдвиге относительно времени сервера (значения времени секундах), например:
[username] 7 / 0.0023 / 0.0102 (3600)
Эта конструкция изначально находится внизу страницы main.html и может быть удалена.

Служебные слова, функции и константы
Интеграл содержит небольшое количество служебных слов и функций, которые дают контроль над происходящим в системе. В фильтрах таблиц и отчетов могут быть использованы следующие слова:
[TODAY] – сегодняшний день, например, 15, если сейчас 15.09.2016 г.
[NOW] – текущие дата и время
[YESTERDAY] – вчерашний день, например, 31.10.2016, если сейчас 1.11.2016 г.
[TOMORROW] – завтрашний день.
[MONTH_AGO] – день месяц назад, например, 28.02.2016, если сейчас 28.03.2016 г.
[USER_ID] – ID пользователя, вошедшего в систему
[USER] – имя пользователя, вошедшего в систему (его также видно в левом нижнем углу любой формы системы)
[TSHIFT] – временной сдвиг на рабочей станции пользователя относительно сервера
! – префикс отрицания последующего условия, например, !% означает «пусто»

В построителе отчетов могут использоваться внутренние функции Интеграла (их немного и все они начинаются с префикса «abn_»). Эти функции нужны аналитику для программирования собственного функционала в Интеграле, такого как формы для быстрого сохранения, контекстные действия и, вообще, любые операции над данными в интеграле:
abn_DATE2STR – преобразование даты в строку (пример: 5 мая 2004 г.)
abn_ID – внутренний идентификатор объекта
abn_NUM2STR – преобразование числа в строку (пример: Пятьсот пятьдесят)
abn_RUB2STR – преобразование суммы в строку с рублями и копейками (Один рубль 00 коп)
abn_REQ – внутренний идентификатор типа реквизита
abn_TYP – внутренний идентификатор типа объекта
abn_ORD – внутренний идентификатор порядка (номера) объекта среди равных ему
abn_UP – внутренний идентификатор родителя объекта
abn_ROWNUM – номер строки в отчете, применим только к вычисляемому полю
abn_URL – результат запроса URL (см. Использование запросов к внешним источникам)
Полный список функций находится в меню Словарь –> Функция.

Также Интеграл поддерживает использование следующих глобальных констант:
{_global_.z} – имя текущей базы данных db из ;
{_global_.action} – имя запрошенной формы или действия ;
{_global_.id} – идентификатор запрошенного объекта ;
{_global_.uri} – путь (URL) к текущей странице, запрошенной пользователем;
{_global_.USER} – имя пользователя, который вошел в систему;
{_global_.USER_ID} – идентификатор пользователя, который вошел в систему;
{_global_.token} – токен пользователя, который вошел в систему.

Еще одна полезная особенность – возможность применения в отчете фильтра по значениям полей данных из произвольных блоков формы. Например, можно обратиться к значениям вышестоящего блока intFormPanels при генерации запроса для блока intPanelFields:

API
При вызове API используется префикс api/ перед именем базы:
/api/{имя базы}/{cmd}[/{id объекта}][?{параметры}]

Обязательный параметр cmd может иметь два префикса для команд на изменение данных:
_d_* - изменение структуры данных (DDL, команды Редактора типов);
_m_* - изменение самих данных (DML, команды базового интерфейса);

Остальные команды возвращают JSON с данными, используемыми системой для построения форм.
Ответом является набор параметров для создания следующего экрана базового интерфейса, как если бы команда была подана формой интерфейса, или сообщение об ошибке.
Все запросы на изменение данных отправляются как POST и требуют токен XSRF (параметр _xsrf).
По команде auth клиент получает токен, который далее передает в заголовке X-Authorization={токен} для всех запросов. Также обычно требуется указать в заголовках 'Content-Type' равный 'application/x-www-form-urlencoded'.

Примеры обращений к API и их полный список здесь – https://tryjob.ru/download/api.xlsx

Known issues
Интеграл постоянно развивается, поэтому в нем неизбежно появляются разного рода дефекты. Если вы столкнулись с какой-либо ошибкой или неудобством, посмотрите, может, это есть в списке ниже. Будем благодарны за сообщение о незарегистрированных проблемах на support@tryjob.ru.