Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
data
js
README.md
cache.appcache
dealer.html
index.html
offline.html

README.md

Тестовое приложение "Счета и реализации для Бухгалтерии предприятия"

  • Пример на jsfiddle работает только в браузерах, на основе v8 (хром, опера, яндекс). Есть ограничения, связанные с фреймом jsfiddle.net и кроссдеменными запросами к данным. Поддержка браузеров ie и mozilla в metadata.js реализована, но для отладки и промышленной эксплуатации рекомендуется chrome или chromium
  • Копия примера по адресу oknosoft.ru/assets/examples/accounting/. Код там не окружен окошками просмотра и живого редактирования, но анализировать и отлаживать его по шагам по {F12} в браузере, пожалуй, даже удобнее, чем в jsfiddle
  • Еще один вариант oknosoft.ru/assets/examples/accounting/dealer.html. Из интерфейса спрятано дерево метаданных, роль главного окна выполняет список счетов

Рассмотрим по шагам, сначала демо-пример в облаке. Затем - развернём тот же пример на локальном компьютере.

Шаг №1 - структура и файлы

Цель:

  • Понять, какие файлы необходимы и достаточны для старта приложения на metadata.js
  • Убедиться, что интерфейс автосгенерированных форм:
    • Работоспособен, позволяет читать и редактировать справочники и документы
    • Не требует написания клиентского кода

Читаем код js на странице примера. Существенные для понимания моменты:

Подключение metadata.js

<script src="//oknosoft.github.io/metadata.js/dist/dhtmlx.min.js"></script>
<script src="//cdn.jsdelivr.net/alasql/latest/alasql.min.js"></script>
<script src="//cdn.jsdelivr.net/metadata/latest/metadata.min.js"></script>

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

Для минималистичного приложения достаточно переопределить 2 метода

$p.settings = function(prm, modifiers){}

В теле этой функции следует указать пути к данным и веб-сервису 1С.

$p.iface.oninit = function(){}

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

Метаданные

Дерево метаданных приложения строится на основании файлов описания meta.json и meta_patch.json. Файлы совершенно одинаковы по структуре и в общем случае, любой из них можно выкинуть либо не заполнять. При старте приложения, система делает попытку прочитать оба файла и суммирует полученные данные во внутреннем объекте Meta.

Подход, при котором описание метаданных разделено на два файла, позволяет упростить разработку и сопровождение, т.к. файл meta.json формируется автоматически обработкой ИнтеграцияОписаниеМетаданныхБП.epf, а файл meta_patch.json предназначен для редактирования разработчиком. Второй файл потребовался, чтобы дополнить метаданные свойствами, которые нельзя задать или переопределить в конфигураторе 1С. Например, ширины и видимость колонок табличной части объекта или признак кеширования.

Код функции $p.settings должен сообщить движку metadata.js, где лежат файлы описания метаданных. За это в примере на jsfiddle отвечает строка:

prm.data_url = "//www.oknosoft.ru/assets/examples/accounting/data/";

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

prm.data_url = "data/";

Следующим, важным служебным файлом, является create_tables.sql. Он формируется автоматически после первой авторизации и входа в программу командой $p.md.create_tables() в консоли браузера. Файл содержит инструкции SQL для создания в памяти браузера таблиц для размещения объектов данных. За установку параметра с адресом SQL отвечает строка:

prm.create_tables = "data/create_tables.sql";

Данные

В зависимости от решаемых задач, часть данных (значения перечислений, справочники, регистры сведений и некоторые документы), могут загружаться при старте программы в память браузера. В процессе работы, доступ к таким данным не будет требовать обращения к серверу. Памятуя про html5 AppCache, эти данные, будучи один раз прочитаны с сервера, при очередных запусках приложения, не создают сетевого трафика. Объекты данных адаптированы для автономной offline работы. На базе metadata.js, можно создавать рабочие места, не требующие постоянного подключения к интернет и обращающиеся к серверу только для асинхронного обмена.

Offline и прочие репликации в нашем примере не используются, а snapshot перечислений и справочников из папки data/zones, позволяет сильно разгрузить сервер 1С как при старте клиентских приложений, так и при оперативной работе пользователей. Папка zones внутри каталога data предназначена для хранения разных снапшотов для разделенной (фреш) публикации 1С. Для неразделенной базы, в настройках необходимо задать:

prm.zone = 0;

Приложения metadata.js могут работать с любыми, неизменёнными конфигурациями 1С на полной поддержке, для которых опубликован стандартный интерфейс Odata. Более того: rest-сервер не обязательно должен являться сервером 1С. Это может быть SAP, MS Dynamics, или иной сервер с поддержкой синтаксиса Odata. Т.к. Rest ориентирован на операции чтения-записи сущностей, для поддержки операций печати, сложной выборки данных и фоновой синхронизации, возможностей стандартного интерфейса Odata недостаточно. Если клиентское приложение должно поддерживать функции печати 1С-ных форм, работу с присоединенными файлами и select-ы к большому числу таблиц, рядом со стандартным сервисом Odata, рекомендуется опубликовать наш http-сервис, в котором поддержаны обращения к отчетам, обработкам и любым публичным методам объектов и общих модулей.

За информирование движка о расположении http-сервисов, отвечает строка:

prm.rest_path = "/a/accounting/%1/odata/standard.odata/";

Шаг №2 - События при старте

Цель:

  • Понять, что происходит при открытии страницы и входе в программу

Загрузка страницы и авторизация

Когда пользователь открывает страницу приложения metadata.js, в памяти компьютера и на экране разворачивается примерно такая (укрупненно) цепочка событий:

  • Браузер читает html заглавной страницы и загружает в память объявленные на этой странице файлы стилей css и скрипты js. Загруженные скрипты сразу выполняются. Создаются структуры, в которые после авторизации будут прочитаны данные приложения, назначаются обработчики событий браузерного объекта window. В процессе выполнения, могут быть загружены дополнительные скрипты и стили
  • Браузер анализирует текст манифеста AppCache и в зависимости от доступности сети и модифицированности файлов, генерирует события AppCache, которые обрабатываются движком metadata.js
    • Если файлы обновлены на сервере, выполняется их обновление в кеше и перезагрузка страницы
    • Если сеть недоступна, переходим в режим offline
    • Если файлы актуальны, переходим к следующему шагу
  • Браузер, после инициализации дерева DOM и выполнения всех загрузочных скриптов, генерирует событие load, которое обрабатывается обрабатываются движком metadata.js
    • Создаётся объект JobPrm, в который загружаются параметры работы программы (rest_path, data_url, create_tables и т.д. - см. выше)
    • Выполняется синтаксический разбор параметров URL, которые могут перекрыть параметры работы программы по умолчанию и сохраненные параметры из localStorage
    • Выполняются пользовательские процедуры перед началом работы программы, если таковые были заданы в JobPrm
    • Управление передаётся переопределяемой процедуре $p.iface.oninit
  • Процедура $p.iface.oninit
    • Создаёт основные области окна программы (в примерах есть раскладки в одну и две колонки, в общем случае, окно может содержать произвольное число областей статического либо изменяемого размера)
    • Создаёт стандартный диалог авторизации. Если приложение рассчитано на анонимных пользователей, либо, если авторизация в сервисе выполняется иными средствами, авторизацию metadata.js можно пропустить
  • После ввода имени пользователя и пароля и нажатия на кнопку Войти, выполняются стандартные шаги инициализации объектов данных. Подробнее см. процедуру log_in модуля events
    • Загружаются метаданные из файлов meta.json и meta_patch.json
    • Делается попытка авторизации, отправкой простого запроса rest-сервису 1С. В случае успеха, переходим к следующему шагу
    • Загружаются данные из файлов data/zones
    • Выполняется дополнительный такт синхронизации с 1С на случай неактуальности снапшота
    • Догружаются элементы справочников, обрезанные по RLS для текущего пользователя
    • Диалог авторизации удаляется из памяти, а управление передаётся клиентскому коду, определенному в $p.iface.oninit. В нашем примере, этот код устанавливает в адресной строке браузера hash#obj=doc.СчетНаОплатуПокупателю&view=oper
  • Браузер, обнаружив изменения в адресной строке, сообщает о них в процедуру $p.iface.hash_route, которая выполняет маршрутизацию: показывает форму объекта или списка или выполняет иные действия в зависимости от хеша url. В нашем случае, открывается форма списка документов Счет на оплату покупателю

Шаг №3 - модификаторы и события объектов

Цель:

  • Понять, как изменить внешний вид форм объекта и обработать события при редактировании реквизитов и табличных частей

Автоформы

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

Автогенерируемые формы списков документов содержат два поля: Номер и Дата. Поля Пометка удаления и Проведен используются для формирования иконки строки списка.

Формы объектов (Документов, Справочников и т.д.) по умолчанию содержат все поля и табличные части, описанные в метаданных. Для отображения шапки и табличных частей, система создаёт отдельные закладки.

Переопределить внешний вид форм можно несколькими способами

  • Дополнить описание метаданных объекта. Например, для формы списка справочника ПодразделенияОрганизаций, в файле meta_patch, указано создать две колонки (Подразделение организации и Организация). Т.к. поле Организация ссылочного типа и элемент справочника подразделения ничего не знает про наименования органирзаций, в разделе fields того же описания, строка "cat_Организации".name as owner приводит к тому, что в запрос к справочнику cat_ПодразделенияОрганизаций будут добавлена таблица cat_Организации, и в качестве текста колонки owner, будут использованы значения поля name связаной таблицы
  • Добавить-удалить-изменить элементы управления в обработчике события При создании автогенерируемой формы
  • Разработать индивидуальную форму объекта или списка. Индивидуальную форму можно назначить формой по умолчанию. В этом случае, она будет использована при автоматической навигации процедурой $p.iface.hash_route. Значение формы по умолчанию можно не менять. В этом случае, изменённую форму можно вызвать либо явно обратившись к её конструктору, либо обработав событие $p.iface.before_route с учетом дополнительных параметров url

Рассмотрим модификацию с помощью meta_patch еще раз на примере формы объекта документа СчетНаОплатуПокупателю

  • В разделе form->obj->head, (шапка документа) определены две группы полей
    • Группа без заголовка с полями Номер, Дата, Организация, Контрагент и ДоговорКонтрагента
    • Группа Дополнительно с полями СтруктурнаяЕдиница, ПодразделениеОрганизации, СуммаВключаетНДС, Ответственный, Комментарий и СуммаДокумента
  • Переопределён тип элемента управления для поля СуммаДокумента, как поле только для чтения. Типы элементов управления для остальных полей назначаются автоматически в соответствии с типом реквизита
  • В разделе form->obj->tabular_sections, указано отображать только табличную часть Товары, а табличные части ВозвратнаяТара и УдалитьУслуги - скрыть
  • Для табличной части Товары явно указан состав колонок, их заголовки, типы элементов управления и ширины по умолчанию