Урок 5. Практика разработки. Часть 2#

В данном уроке мы рассмотрим:

  1. Типы объектов

  2. Состояния классов

  3. Динамическое управление редактируемостью полей

  4. Действия на перевод состояния

Типы объектов#

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

Состояния#

Состояния класса позволяют управлять бизнес-логикой объекта. Руководство разработчика: Тип объекта # Переходы состояний

Практические задания#

Добавление атрибутов типа объекта и состояния#

  • В классе Lbr_OutOrder, Lbr_InOrder и Lbr_InAct добавьте атрибуты:

name

attribute-type

caption

Дополнительно

idState

Long

Состояние

Ссылочный на объект, Ссылается на класс Btk_ClassState, не копируется при выполнении копирования

idStateMC

Number

Номер состояния

Не видимый, не копируется при выполнении копирования, является порядковым номером состояния (isStateMC="true")

idObjectType

Long

Тип

Ссылочный на объект, Ссылается на класс Btk_ObjectType, хедлайн

  • Запустите кодогенерацию по этим классам и запустите генератор таблиц для них

Добавление состояния для классов#

  • Откройте карточку класса Lbr_InAct (Настройка системы \ Сущности > Классы) и добавьте состояния:

Системное имя

Наименование

Порядковый номер

Стартовое состояния

Create

Оформляется

100

1

Executed

Выполнен

300

0

  • Для классов Lbr_InOrder и Lbr_OutOrder в api сделайте метод regState для регистрации аналогичных состояний и пропишите его в odm в тэге dbData. Руководство разработчика: Тип объекта # Регистрация состояний

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

Создание закладки для класса через справочник закладок#

Данные закладки будут нужны для дальнейшей настройки на типе объекта.

Настройка типов объектов#

  • Создайте тип объекта с кодом, наименованием и кр. наименованием Lbr_InAct - Приходная накладная через справочник типов объекта и установите на нем флаг по умолчанию, настройте для него закладку с позициями и переходы состояний. Доступные закладки для класса будут отображаться, если установить в фильтре флаг Отображать неактивные

  • Для того, чтобы при создании объекта подставлялся тип по умолчанию, в Lbr_InActApi переопределите метод insert и пропишите в конце вызов установки типа объекта по умолчанию setidObjectType(rop, Btk_ObjectTypeApi().getDefaultObjType(idClass))

  • В Lbr_InAct.avm отображении Card подключите закладки от типа объекта. Руководство разработчика: Тип объекта # Детализация виде закладок

  • Там же у атрибута idObjectTypeHL измените тип редактора на выпадающий список с lookupQuery="gtk-Btk_ObjectTypeAvi#MainLookup"

  • В Lbr_InActApi создайте метод regObjectType для регистрации еще одного типа Lbr_InAct_Add - Дополнительная приходная накладная, с параметром bpIsDefault = 0. Там же пропишите регистрацию закладок для типа и переходов состояния, пропишите метод в odm. Запустите генерацию таблиц по данному классу. Руководство разработчика: Тип объекта # Регистрация подкласса, типа объекта, закладок для типа и переходов состояний

  • Для классов Lbr_InOrder и Lbr_OutOrder сделайте аналогичную настройку в avm и в Api().insert, также в Api сделайте метод для регистрации типа по умолчанию с кодом и наименованием из класса. Там же пропишите регистрацию закладок для типа и переходов состояния, пропишите метод в odm, с зависимостями от предыдущих скриптов regTab и regState. Запустите генерацию таблиц по данным классам.

Так как тип объекта и его коллекции является классами с разделяемым режимом кеширования (Shared), то необходимо после любых изменений на них, сбрасывать Shared кэш

Разработка бизнес логики#

Внимание

Не используйте copyAro для получения значений атрибутивного состава rop, так как это увеличивает расход оперативной памяти, для получения значений атрибута следует применять rop.get(_.атрибут)

Вычисление заголовка с учетом типа объекта#

  • В Api классов-документов измените вычисление заголовка calcHeadLine, заголовок должен быть в формате {(Краткое наименование из типа объекта).nvl(HL класса)} {sNumDoc} от {dDoc в формате дд.мм.гггг}.

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

Динамическое управление редактируемостью полей#

  • В Avi документов для карточек переопределите сеттер состояния setidState, в конце пропишите методы для корректного срабатывания checkWorkability мастера и деталей, для того чтобы последующие задания работали корректно при переводе состояния:

//не обязательные действия
//завершение транзакции
session.commit()
//снятие блокировки
Btk_FormSessionApi().closeLockUnit()

//необходимые действия
//обновление карточки
selection.refreshItem()
//вызов checkWorkability в карточке
selection.checkWorkability()
//вызов checkWorkability в деталях
selection.cwaDetails()
  • Для реализации динамического управления редактируемостью в Avi позиций документов, для отображений List_idDoc и List_idInAct переопределите метод checkWorkability, напишите блокировку добавления, удаления, редактирования позиций, если номер состояния документа отличен от 100. Можно воспользоваться данными методами:

//переменная для управления редактируемостью
val bvRO = getVar("super$idStateMC").asNNumber.isDistinct(100.nn)
//для одного атрибута
selection.attrs("Имя атрибута").isReadOnly = bvRO
//для списка атрибутов
selection.attrs().foreach(_.isReadOnly = bvRO)
//для операций
selection.opers("Имя операции").isEnabled = !bvRO
  • В Avi документов для карточек переопределите checkWorkability, напишите блокировку на редактирование всех полей, кроме idState, idStateHL и nSum, если номер состояния документа отличен от 100

Действия на перевод состояния#

В Lbr_InActApi:

  • Создайте метод проверки документа (например validateDoc), на вход будет rop документа.

  • В нем пропишите вызов ошибки, если не будут выполнены какие либо условия (указаны ниже). Ошибку можно сделать одну общую с не выполненными условиями или отдельную по каждому условию. Вызов ошибки осуществляется методом throw AppException("Текст ошибки"). Перечень условий:

    1. Заполнены атрибуты документа (дата, организация, библиотекарь)

    2. Наличие хотя бы одной записи в позициях

    3. Заполнены атрибуты в позициях (книга, количество)

  • Переопределите сеттер состояния (setidState), в начале метода пропишите вызов метода проверки, если номер нового состояния будет >=300 и номер старого состояния < 300.

  • В Lbr_InOrderApi и Lbr_OutOrderApi напишите аналогичную логику, только без проверки количества в позиции.

Проверка при удалении#

в Api документов переопределите метод delete и напишите в начале проверку, чтобы нельзя было удалить документ, если он находится не в состоянии Оформляется