# Урок 4. Практика разработки. Часть 1 В данном уроке мы рассмотрим: 1. Миксины 2. Документы 3. Коллекции 4. Автонумерацию на атрибутах класса ## Миксины Особый вид классов, которые служат для хранения данных из разных классов. Используются для построения общих списочных форм различных диалогов подбора в пользовательских интерфейсах, а также для удобства обработки данных в прикладной бизнес-логике. Миксин позволяет объединить несколько разных таблиц вместе что дает возможность использовать внешние ключи и индексы на данное объединение. Пример: миксин `Bs_Settler` - `Сторона расчета`, которая объединяет в себе классы `Bs_Contras` - `Контрагент` и `Bs_Person` - `Физические лица`. [Руководство разработчика: Класс # Миксин](books/AppGuide/030_class/060_класс.md#миксин-mixin) ## Документы Документ – это прикладной объект, который хранит данные о событиях или операциях на предприятии. Пример: Заявка на отгрузку; Приходная накладная; Акт сверки. [Руководство разработчика: Класс # Cупертипы классов](books/AppGuide/030_class/060_класс.md#супертипы-классов) ## Коллекции Коллекции представляют собой классы, объекты которых не имеют права на самостоятельное существование и могут быть созданы только для объектов других классов. Коллекции применяются в качестве табличных частей документов или логических развязок между классами. Пример: Позиции накладной; Позиции складского ордера [Руководство разработчика: Класс # Коллекции](books/AppGuide/030_class/060_класс.md#коллекции) ## Автонумерация Процесс автоматической выдачи значения для атрибута класса. В основе лежит выдача порядкового номера (числа), которое может быть преобразовано в значение по маске. [Руководство разработчика: Сервисы класса # Автонумерация](books/AppGuide/030_class/070_сервисы_класса.md#автонумерация) ## Практические задания ```{attention} Соблюдайте общие принципы наименования. [Руководство разработчика: Языки разработки # Общие принципы наименования](books/AppGuide/020_common/040_языки_разработки.md#общие-принципы-наименования) ``` ### Добавление автонумерации без разреза - В классе `Lbr_Author` сделайте автонумерующимся поле `sCode`, без разреза и маской с дополнением до 4 нулей слева (пример `0001`, `0002`... `0010`). Также уберите обязательность для ввода, чтобы не было ошибки при сохранении. ### Создание классов #### Миксин для документов - Создайте директорию `document` и в нем класс `Lbr_Document` - `Документ` с типом `mixin` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | gidRef | Varchar | Идентификатор | Не видимый (`isVisible="false"`)| | sNumDoc | Varchar | № | | | dDoc | Date | Дата документа | Редактор даты (`editorType="datePick"`) | | idDepOwner | Long | Организация | Ссылочный на объект, ссылается на класс Bs_DepOwner | - Удалите поля id, idClass, gid, так как в миксине они не нужны (если есть) - Запустите кодогенерацию по данному классу и запустите генератор таблиц для него - Добавьте в `Lbr_MainMenuAvi` пункт `Миксин для документов` под `Тесты и отладка`, в котором пропишите открытие умол. списка для `Lbr_DocumentAvi` #### Документ выдача книг - Создайте директорию `outorder` и в нем класс `Lbr_OutOrder` - `Выдача книг` с типом `document` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | sNumDoc | Varchar | № | Автонумерующийся в разрезе организации и года (от даты), хедлайн (`isHeadLine="true"`), не копируется при выполнении копирования (`isCopyInCopyObject="false"`)| | dDoc | Date | Дата | Хедлайн, значение атрибута по умолчанию - sysdate (`defaultValue="sysdate"`), не копируется при выполнении копирования, редактор даты | | idLibrarian | Long | Библиотекарь | Ссылочный на объект, Ссылается на класс Bs_Person | | idPerson | Long | Читатель | Ссылочный на объект, Ссылается на класс Bs_Person | | idDepOwner | Long | Организация | Ссылочный на объект, Ссылается на класс Bs_DepOwner | - Подключите к нему миксин `Lbr_Document` - В этой же директории создайте класс `Lbr_OutOrderDet` - `Позиции` с типом `collection` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | idDoc | Long | Выдача книг | Ссылочный на объект, Ссылается на класс Lbr_OutOrder, не видимый, формирования отображения выборки для вывода данных в качестве коллекции (`genListCollectionRep="true"`) | | nRow | Number | № п/п | Не копируется при выполнении копирования | | idBook | Long | Книга | Ссылается на класс Lbr_Book | - Укажите данный класс как коллекцию в классе `Lbr_OutOrder` - Запустите кодогенерацию для `Lbr_OutOrder` и `Lbr_OutOrderDet`, запустите генератор таблиц для обоих классов - В avm документа для карточки и списка подключите закладку с позициями, в списке по умолчанию закладка не видима - В avi документа для карточки на операцию сохранения пропишите обновление формы - Добавьте в `Lbr_MainMenuAvi` пункт `Выдача книг` под `Документы`, в котором пропишите открытие умол. списка для `Lbr_OutOrderAvi` ```{note} При выборе данных из справочника физ. лиц в фильтре установите флаг `Не является сотрудником`, для того, чтобы отображались все строки. ``` #### Документ возврат книг - Создайте директорию `inorder` и в нем класс `Lbr_InOrder` - `Возврат книг` с типом `document` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | sNumDoc | Varchar | № | Автонумерующийся в разрезе организации и года (от даты), хедлайн, не копируется при выполнении копирования| | dDoc | Date | Дата | Хедлайн, значение атрибута по умолчанию - sysdate, не копируется при выполнении копирования, редактор даты| | idLibrarian | Long | Библиотекарь | Ссылочный на объект, Ссылается на класс Bs_Person | | idPerson | Long | Читатель | Ссылочный на объект, Ссылается на класс Bs_Person | | idDepOwner | Long | Организация | Ссылочный на объект, Ссылается на класс Bs_DepOwner | - Подключите к нему миксин `Lbr_Document` - В этой же директории создайте класс `Lbr_InOrderDet` - `Позиции` с типом `collection` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | idDoc | Long | Возврат книг | Ссылочный на объект, Ссылается на класс Lbr_InOrder, не видимый, формирования отображения выборки для вывода данных в качестве коллекции | | nRow | Number | № п/п | Не копируется при выполнении копирования | | idBook | Long | Книга | Ссылается на класс Lbr_Book | - Укажите данный класс как коллекцию в классе `Lbr_InOrder` - Запустите кодогенерацию для `Lbr_InOrder` и `Lbr_InOrderDet`, запустите генератор таблиц для обоих классов - В avm документа для карточки и списка подключите закладку с позициями, в списке по умолчанию закладка не видима - В avi документа для карточки на операцию сохранения пропишите обновление формы - Добавьте в `Lbr_MainMenuAvi` пункт `Возврат книг` под `Документы`, в котором пропишите открытие умол. списка для `Lbr_InOrderAvi` #### Документ приходная накладная - Создайте директорию `inact` и в нем класс `Lbr_InAct` - `Приходная накладная` с типом `document` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | sNumDoc | Varchar | № | Автонумерующийся в разрезе организации и года (от даты), хедлайн, не копируется при выполнении копирования | | dDoc | Date | Дата | Хедлайн, значение атрибута по умолчанию - sysdate, не копируется при выполнении копирования, редактор даты | | idLibrarian | Long | Библиотекарь | Ссылочный на объект, Ссылается на класс Bs_Person | | nSum | Number | Сумма | Денежный редактор (`editorType="currency"`)| | idDepOwner | Long | Организация | Ссылочный на объект, Ссылается на класс Bs_DepOwner | - Подключите к нему миксин `Lbr_Document` - В этой же директории создайте класс `Lbr_InActDet` - `Состав накладной` с типом `collection` и атрибутами: |name|attribute-type|caption|Дополнительно| |-|-|-|-| | idInAct | Long | Приходная накладная | Ссылается на класс Lbr_InAct, не видимый, формирования отображения выборки для вывода данных в качестве коллекции | | nRow | Number | № п/п | Не копируется при выполнении копирования | | idBook | Long | Книга | Ссылается на класс Lbr_Book | | nQty | Number | Кол-во | | | nPrice | Number | Цена | Денежный редактор | | nSum | Number | Сумма | Денежный редактор | - Укажите данный класс как коллекцию в классе `Lbr_InAct` - Запустите кодогенерацию для `Lbr_InAct` и `Lbr_InActDet`, запустите генератор таблиц для обоих классов - В avm документа для карточки и списка подключите закладку с позициями, в списке по умолчанию закладки сделайте не видимыми - В avi документа для карточки на операцию сохранения пропишите обновление формы - Добавьте в `Lbr_MainMenuAvi` пункт `Приходные накладные` под `Документы`, в котором пропишите открытие умол. списка для `Lbr_InActAvi` ### Разработка бизнес логики #### Вычисление заголовка - В `Api` классов-документов переопределите метод вычисление заголовка `calcHeadLine`, заголовок должен быть в формате `{HL класса} № {sNumDoc} от {dDoc в формате дд.мм.гггг}`. - Для созданных ранее объектов пересчитайте заголовки, для этого в карточках классов, под молотком и ключом запустите операцию `Пересчитать заголовки и мнемокоды объектов класса`. Для проверки можно посмотреть данные столбца sheadline_dz в таблицах. #### Установка порядкового номера для позиций - В `Api` позиций документов переопределите метод `insertByParent` и напишите установку значения в поле `nRow`, как максимальный текущий номер в позициях + 1. Если позиций еще нет, то первая позиция должна начинаться с 1. Можно воспользоваться `scala` функцией `reduceOption(_ max _).getOrElse(0.nn)` - В `Avi` позиций документов для отображений `List_idDoc` или `List_idInAct` переопределите метод `onRefresh` и допишите сортировку по полю `nRow`, используя `sortBy`. #### Пересчитываемые поля Добавьте пересчеты для приходной накладной `Lbr_InActDetApi`: - Переопределите методы установки цены и количества (сеттеры `setnPrice` и `setnQty`), добавьте логику вычисления суммы в позиции с округление до 2х знаков - Переопределите сеттер суммы, добавьте вычисление цены в позиции с округление до 2х знаков - Добавьте пересчет общей суммы документа при изменении суммы в позициях или удалении самой позиции - На сеттеры цены, количества и суммы добавьте проверку на отрицательный ввод, вызов ошибки осуществляется методом `throw AppException("Текст ошибки")` `Lbr_InActDetAvi`: - Переопределите сеттеры цены, количества и суммы, добавьте в конце обновление текущей записи (`selection.refreshItem()`) и обновление карточки мастера (`selection.master.refreshItem()`) - Переопределите метод удаления (`delete`) и пропишите в конце обновление карточки мастера `Lbr_InAct.avm.xml`: - Сумму документа сделайте не редактируемой в карточке