Установка значений атрибутов по умолчанию

Значения по умолчанию, заданные для атрибутов каких-либо классов, используются для автозаполнения соответствующих полей на формах редактирования. Ранее значение по умолчанию для одного из атрибутов было указано при создании диаграммы классов - была указана текущая дата для атрибута “CreateDate” класса “Document”:

Класс Document

Такой синтаксис использутся для указания значения по умолчанию, которое будет использоваться в том случае, если соответствующее поле на форме редактирования не заполнено. Чаще всего такая потребность возникает при создании новой записи, у которой часть полей заполняется таким образом автоматически.

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

Document → Выделить класс → Открыть форму редактирования (шестеренка) → Правка → Атрибуты → Кнопка редактирования в строке атрибута

Дефолтное значение даты создания класса Document

В открывшейся форме можно увидеть заданное по умолчанию значение для атрибута “CreateDate(DataZapolneniya)”. Установить следующие свойства для атрибута “Number(Nomer)”

DefaultValue → 1,
Autoincrement → +,
NotNull → + (обязательно для автоинкремента).

Дефолтные значения атрибутов класса Document

После сохранения свойств атрибута “Number” класс на диаграмме будет иметь следующий вид:

Класс Document с автозаполнением

Автоинкрементными возможно сделать только атрибуты типа int.


Самостоятельно: изменить свойства атрибутов следующих классов:

Класс заказа Order

Status ‒ New

Класс накладной Invoice

Status ‒ New

Класс склада Storehouse

Number ‒ с 1, инкремент

Класс товара Product

ProductCode ‒ с 1, инкремент

Класс сотрудника Employee

Number ‒ с 1, инкремент


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

Настройка вычислимых атрибутов

Ранее был создан вычислимый атрибут на диаграмме классов ‒ это атрибут “Cena” (Стоимость заказа) класса “Order” (Заказ). Он помечен символом “/”:

Нехранимый атрибут Cena класса Order

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

Для указания DataServiceExpression следует открыть окно редактирования свойств класса (кликнуть на классе, выбрать “шестеренку”) в строке нужного атрибута в столбце «DataService Expression», нажать на кнопку редактирования. В открывшемся окне можно задать несколько значений для разных типов сервисов данных: для этого нажать кнопку Создать DataServiceExpression. В столбце «DataService» нужно указать тип сервиса данных, с которым будет использоваться SQL-выражение; в столбце «DataService Expression» - само SQL-выражение (SELECT SUM(CenaSNalogami * Kolichestvo) FROM OrderItem WHERE OrderItem.Order_m0 = STORMMainObjectKey).

Добавление DataServiceExpression для атрибута Cena класса Order

Для атрибута Cena можно написать универсальное SQL-выражение, которое будет работать с любым SQL-совместимым сервисом данных, поэтому достаточно одного выражения с указанием SQLDataService в качестве типа сервиса данных.

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

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

/// <summary>
/// Cena.
/// </summary>
// *** Start programmer edit section *** (Order.Cena CustomAttributes)

// *** End programmer edit section *** (Order.Cena CustomAttributes)
[ICSSoft.STORMNET.NotStored()]
[DataServiceExpression(typeof(SQLDataService), "SELECT SUM(CenaSNalogami * Kolichestvo) FROM OrderItem WHERE OrderItem.Order_m0 = STORMM" +
    "ainObjectKey")]
public virtual double Cena
{
    get
    {
        // *** Start programmer edit section *** (Order.Cena Get)
        if (!CheckLoadedProperty(nameof(OrderItem)))
        {
            throw new InvalidOperationException($"The '{nameof(OrderItem)}' property not loaded.");
        }

        double sum = 0;
        foreach (OrderItem item in OrderItem)
        {
            sum += item.CenaSNalogami * item.Kolichestvo;
        }

        return sum;
        // *** End programmer edit section *** (Order.Cena Get)
    }
    set
    {
        // *** Start programmer edit section *** (Order.Cena Set)

        // *** End programmer edit section *** (Order.Cena Set)
    }
}

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

Добавить отдельное представление в класс OrderItem со свойствами Kolichestvo и CenaSNalogami:

Добавление представления для класса OrderItem

Добавить только что созданное представление в качестве детейла в представление OrderL класса Order:

Обновление представления в классе Order

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

Настройка типов данных

Настройка типов данных у атрибутов классов ‒ важный шаг, который определяет сопоставление типов данных для классов на диаграмме с классами в коде приложения или таблицами в базе данных, а также генерацию правил валидации в приложении. Это будет показано на примере класса Invoice (Накладная):

Поле ShipmentDateTime класса Invoice

В данном классе у атрибута ShipmentDateTime (“Дата и время отгрузки”) указан тип “DateTime”. В связи с этим, если при сохранении модели на бэкенде это поле будет пустым, то оно по умолчанию будет заполнено значением “01.01.1901”. Это связано с тем, что в C# значение типа “DateTime” не может принимать нулевые (null) значения: в момент сохранения записи происходит автоприсвоение минимального валидного значения (01.01.1901). Однако в реальном приложении это поле в принципе может быть пустым (не по каждой накладной может быть осуществлена отгрузка в заданный момент времени).

Для решения описанной выше проблемы необходимо сопоставить тип данных на диаграмме класов с типом данных “DateTime?” при генерации приложения на языке C#.

Проверить, есть ли такой вариант среди типов, доступных “из коробки” во Flexberry Designer, можно, открыв карту типов:

Настройка → Настройка проекта → Кнопка "Карта типов"

Свойства модели

Карта типов модели

В карте типов имеется три Nullable-типа: для даты, а также для целого и вещественного типа. Их можно использовать для решения подобной задачи, но, во-первых, не всегда необходимые Nullable-типы будут существовать в карте типов, а, во-вторых, всё-таки рекомендуется использовать стандартные типы языка C#, которые допускают значение null. Поэтому рекомендуется добавить свой собственный тип.

Следует добавить для новых типов данных отдельную диаграмму классов (Типы данных):

Создание диаграммы классов "Типы данных"

На созданной диаграмме создадать новый класс с именем “tDateTime” и стереотипом “typedef” (данный класс можно сразу свернуть, т.к. у него не будет никаких атрибутов и методов):

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

Настройка → Настройка проекта → Кнопка "Карта типов"

Карта типов модели с типом tDateTime

После создания класса со стереотипом “typedef”, в карте типов появился соответствующий тип данных. Присвоить ему значение System.DateTime? в поле “C#”. Заполнить значение для PostgreSQL (требуется указать сопоставление нового типа данных с типом TIMESTAMP(3)).

Карта типов БД PostgreSQL

Обязательно сохранить свойства модели (верхний правый угол страницы)!

Далее заменить соответствующие типы данных у атрибутов на диаграмме классов:

Карта типов БД

Можно не заменять тип данных у атрибута "CreateDate" класса "Document", т.к. этот атрибут по умолчанию заполняется текущей датой.

Итог

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

Итоговый вариант диаграммы классов перед генерацией приложений и базы данных выглядит следующим образом:

Диаграмма классов "Сущности"

Перейти