Какие особенности необходимо учитывать при разработке на ISBL. Часть 1

14 5

Введение

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

В данной статье будут рассмотрены следующие ситуации:

  • создание заданий для неавтоматизированных работников;
  • отсутствие исполнителя роли;
  • учет прав доступа;
  • медленное открытие больших справочников;
  • работа с неутвержденными записями;
  • учет локализации на формах.

Создание заданий для неавтоматизированных работников

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

  User = GetUserByEmployeeCode(EmployeeCode)
  if VarIsNull(User)
    // Работник не автоматизирован
    // Найти пользователя для неавтоматизированного работника,
    // напр. руководитель/секретарь
  else
    // Работник автоматизирован
  endif

Отсутствие исполнителя роли

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

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

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

Чтобы избежать данных проблем следует исполнителя блока задавать в качестве параметра типа User List, а сам параметр заполнять при старте задачи на этапе «Возможность старта». Если число записей в списке исполнителей роли равно нулю, выводить ошибку. Пример:

  RoleUser = ServiceFactory.GetRoleByName('InvoiceClerks')
  PerformerUserList = ServiceFactory.GetRoleMembers(RoleUser)
  if PerformerUserList.Count > 0
    // Исполнители присутствуют
    Object.WorkflowParams.ValueByName("Performers").Value = PerformerUserList
    ...
  else
    // Исполнитель по роли не определен
    Raise(CreateException(...))
  endif

Учет прав доступа

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

  1. При работе с документами у пользователя возможно отсутствие прав доступа на просмотр, как минимум.
  2. При работе со справочниками все выглядит немного иначе. При определении прав доступа используются следующие критерии:
    • личные права на записи справочника с определенным значением реквизита-фильтратора;
    • групповые права – права, назначенные группам, в которые входит пользователь;
    • настроенные фильтраторы – доступ к данным компоненты ограничивается по значениям ее реквизитов-фильтраторов;
    • привилегия «Полный доступ к компонентам» – привилегия, назначенная пользователю или группам, в которые входит пользователь. Предоставляет полный доступ ко всем справочникам.
  3. При работе с задачами пользователь может быть не включен в список наблюдателей или же исполнителей.

Медленное открытие больших справочников

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

  • Использование функций AddWhere. Преимуществом данных функций является то, что данные фильтраторы отрабатывают на стороне сервера и клиент по факту получает уже отфильтрованный справочник (с ограниченным числом записей). Но при использовании данного способа следует удалять фильтрацию при закрытии справочника. В качестве примера я приведу отображение работников из подразделения ИВЦ, используя функцию AddWhere:
  DepartmentID = 102765 // ИД подразделения ИВЦ
  EmployeesRef = References.РАБ.GetComponent()
  EmployeesTableName = EmployeesRef.TableName
  DepartmentFieldName = EmployeesRef.Requisites('Подразделение').SQLFieldName
  // Добавляем фильтратор
  AddWhere = EmployeesRef.AddWhere(Format("%s.%s = '%s'"; ArrayOf(EmployeesTableName;
    DepartmentFieldName; DepartmentID)))
  EmployeesRef.Open() // Открываем справочник
  EmployeesRef.ComponentForm.Show() // Отображаем форму с записями
  EmployeesRef.Close() // Закрываем справочник
  EmployeesRef.DelWhere(AddWhere) // Удаляем фильтратор

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

  • Иерархия справочников, позволяющая ускорить загрузку данных. При открытии справочника в иерархическом представлении загружаются только записи текущего узла дерева. При открытии справочника в обычном режиме загружаются сразу все его записи. Принудительное включение иерархии рассмотрено на примере справочника "Журналы регистрации":
  ГДЛСпр = References.ГДЛ.GetComponent()
  Form = ГДЛСпр.ComponentForm
  ГДЛСпр.View.HierarchyName = 'ByRegistrationPlaces'
  Form.Show()

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

  • текущий период, накладывающий жесткий критерий на дату создания записи справочника. В этом случае в списке будут видны только те записи, период действия которых не установлен или установлен и попадает в текущий период. Текущий период можно устанавливать из проводника системы и из списка записей любого справочника. Во всех справочниках системы используется один и тот же текущий период. Чтобы установить текущий период можно воспользоваться одним из представленных способов:
    • в проводнике системы с помощью быстрого запуска откройте компоненту «Текущий период»;
    • в списке записей любого справочника на вкладке Главная в группе Список в выпадающем списке  «Фильтр по периоду» выберите пункт «Изменить период».

    В результате, откроется окно «Текущий период». В нем необходимо указать начало и конец периода. Чтобы установить или снять фильтр по текущему периоду, в списке записей на вкладке Главная в группе Список нажмите на кнопку  Фильтр по периоду. Если фильтр не был установлен, то он будет установлен. В этом случае в списке будут видны только те записи, период действия которых не установлен или установлен и попадает в текущий период. Период действия записи задается в свойствах записи. Если фильтр был установлен, то он будет снят.

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

      Sender.Component.Params.Add(CURRENT_PERIOD_IS_REQUIRED; null)
    

    В результате для справочника будет установлен фильтр по текущему периоду и на ленте на вкладке "Главная" в группе Список кнопка "Фильтр по периоду" будет недоступна для снятия текущего периода.

 Работа с неутвержденными записями

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

На рисунке представлен пример данной особенности:

Как видно из рисунка, кнопка «Работники», осуществляющая поиск по «Должности», доступна изначально, хотя должность ещё не заполнена: поиск ведется по наименованию в карточке, и легко можно получить ошибку при нажатии на кнопку.

Рассмотрим пример блокировки кнопки на ленте. Для осуществления блокировки, необходимо указать в событии "Показ" секции "Форма-карточка" следующий код:

  Object.Form.Actions.FindAction('&Установки').Enabled = Object.SYSREQ_RECORD_STATUS == '+'
  Object.Form.Actions.FindAction('&Организация').Enabled = Object.SYSREQ_RECORD_STATUS == '+'

Тогда при создании новой записи осуществится блокировка кнопок, отвечающих за действия "&Установки" и "&Организация" и будет иметь следующий вид:

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

  Object.Form.Actions.FindAction('&Установки').Enabled = Object.SYSREQ_RECORD_STATUS == '+'
  Object.Form.Actions.FindAction('&Организация').Enabled = Object.SYSREQ_RECORD_STATUS == '+'

В результате, заполнив реквизиты, форма примет следующий вид:

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

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

Здесь:

  • Доступно - кнопка будет доступна всегда (по умолчанию).
  • Доступно при просмотре - кнопка будет доступна при просмотре записи.
  • Доступно при редактировании - кнопка будет доступна при редактировании записи.
  • Недоступно - кнопка будет всегда недоступна.
  • Недоступно без данных - кнопка будет недоступна, если не заполнен ни один из реквизитов.

Учет локализации на формах

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

В качестве примера можно рассмотреть случай, когда заголовок поля From сместился на форме из-за локализации. В русской локализации поле называется «С». Как видно, длины слов «С» и «From» отличаются. В следствие чего получилось смещение, представленное на рисунке ниже:

Заключение

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

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

Зачем?

Анна Долганова
DepartmentID = 102765 // ИД подразделения ИВЦ

Я понимаю, что это пример, но раз уж пошла такая пьянка - зашивать в код ИДшники может быть чревато поломкой кода :)

А по существу - спасибо за такую подробную статью, сколько их вообще планируется в этом цикле?

Николай Шестаков
Зачем?

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

зашивать в код ИДшники может быть чревато поломкой кода :)

Это всего лишь пример. Согласен, что так делать не стоит.

сколько их вообще планируется в этом цикле?

Думаю пара частей точно будет:)

Андрей Куров
Если закрыть справочник, а в дальнейшем открыть, то далеко не во всех случаях фильтрация удаляется.

А можно пример, когда надо справочник закрыть и потом снова открыть в одном скрипте?

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

Sergey Dmitriev

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

возможно, что работник является неавтоматизированным

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

параметр заполнять при старте задачи на этапе «Возможность старта»

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

 

 

 

 

Авторизуйтесь, чтобы написать комментарий