[ELMA3] Создание серверного модуля для приложения
Перед созданием модуля ознакомьтесь со страницей Создание модуля для приложения.
Основы взаимодействия модуля и основной конфигурации
Для начала необходимо объяснить, что же такое модуль и как он должен взаимодействовать с основной конфигурацией (платформой и ядром) приложения. Модуль – это отделяемая часть бизнес логики приложения, использующая возможности ядра и платформы для интеграции с другими модулями и с платформой системы. Другими словами, модуль – значительный блок логики и данных в контексте всего приложения. Взаимодействие модуля и других частей конфигурации происходит на 3-х уровнях:
- Модель данных – на этом уровне можно создавать собственные модели, расширять и наследовать уже существующие в других частях;
- Точки расширения – через этот механизм происходит основная часть интеграции в приложение, тут вы просто реализуете определенные интерфейсы и получаете требуемый функционал;
- События – простая событийная модель позволяет осуществлять еще более глубокую интеграцию.
Сам по себе модуль, обычно, представляет набор библиотек и веб-приложение для отображения данных. Модули могут быть самыми разными, от простых кусочков интеграции (например, интеграция модуля задач и модуля документов), до сложных самостоятельных модулей (например, модуль Управления проектами).
Создание модуля
Для создания модуля можно использовать Visual Studio 2010/2013/2015/2017 и плагин для разработки ELMA. Структура модуля одинакова для той и другой версии VS. Примеры сделаны в 2013 версии.
Чтобы создать модуль, нужно открыть VS – Создать проект (New Project) – Модуль для системы ELMA3.
Результатом создания будет решение с двумя проектами:
где EleWise.ELMA.CRMExtension – серверная часть модуля, а EleWise.ELMA.CRMExtension.Web – веб-часть модуля.
Файл AssemblyInfo.md теперь создается сразу. Он находится в серверной части модуля. Здесь вы можете задать необходимые Вам отображаемой имя, описание и т.д.
Создание и подготовка модели данных
Перед созданием полей по умолчанию необходимо в проект добавить сборку EleWise.ELMA.Security.
После всех приготовлений мы получаем проект, в котором можно добавлять новые модели и расширять существующие. В нашем примере, мы создадим модуль Работа с клиентами, в котором будет отображаться список компаний, будет возможность создавать\изменять компании. Также будет возможность прикреплять к компании документ и файл с комментарием. У компании будут поля:
- Наименование;
- Дата создания;
- Дата изменения;
- Автор создания;
- Автор изменения;
- ИНН;
- КПП.
Для демонстрации этих полей будет достаточно. Сначала добавим новую сущность в папку Models, назовем ее Company и добавим в нее свойства по умолчанию: Наименование, Автор создания, Автор изменения, Дата создания, Дата изменения. Для создания сущности нажимаем правой кнопкой мыши по папке Models – Add – New Item – ELMA Entity Interface.
Свойства Наименование, Автор и Дата создания необходимо отметить как обязательные для заполнения. Добавим свойства ИНН и КПП строкового типа. Для объекта Company нужно установить флажок Генерировать фильтр.
Подготовка бизнес логики
Вся бизнес логика приложения должна быть вынесена в специальные классы-менеджеры. Создадим свой класс-менеджер для работы с Компаниями:
public class CompanyManager : EntityManager<ICompany, long>
Обратите внимание, ICompany – это интерфейс. При создании сущности в Дизайнере на самом деле генерируется интерфейс, на основе свойств, добавленных в сущность. Второй параметр – это тип идентификатора сущности, он по умолчанию long, но это можно изменить при необходимости. Базовый класс EntityManager уже содержит необходимые методы для создания, сохранения, загрузки и удаления сущности. Особое внимание необходимо уделить тому, как создаются новые экземпляры сущности. Поскольку мы работаем с интерфейсами, то создавать напрямую объекты мы не можем, но есть два способа сделать это быстро и правильно:
- Вызвать метод Create() в менеджере.
- Использовать методы Create() класса EleWise.ELMA.Model.Services.InterfaceActivator.
На самом деле в первом случае делается перевызов второго варианта. В этом классе нужно определять любую логику работы с сущностями. В любом месте приложения будет доступен глобальный экземпляр вашего менеджера через статическое свойство Instance. Чтобы переопределить и возвращать сразу нужный тип менеджера, добавьте в ваш класс:
public new static CompanyManager Instance { get { return Locator.GetServiceNotNull<CompanyManager>(); } }
В нашем модуле нам потребуется разграничивать права пользователей. У нас будет всего 2 уровня доступа:
- Доступ к модулю (глобально возможность видеть модуль).
- Возможность редактировать компанию (это право есть только у автора компании).
Первый – это глобальный уровень, он назначается ролям через интерфейс администрирования. Второй – это уровень доступа на сущность, он зависит от значения поля Автор сущности. Для создания этих уровней необходимо использовать точку расширения EleWise.ELMA.Security.Services.IPermissionProvider, в ней необходимо реализовать 2 функции и 3 свойства:
- GetPermissions() – функция, возвращает набор готовых экземпляров класса EleWise.ELMA.Security.Permission;
- GetPermissionStereotypes() – функция, возвращает набор предустановленных прав для этого модуля, они будут созданы при подключении модуля;
- LocalizedItemsNames – свойство, возвращает локализированные имена привилегий;
- LocalizedItemsDescriptions – свойство, возвращает локализированные описания привилегий;
- LocalizedItemsCategories – свойство, возвращает локализированные имена категорий.
Более подробно смотрите страницы Настраиваемые привилегии на объекты и Привилегии. В нашем случае реализация довольно простая:
[Component] public class CRMExtensionPermissionProvider : IPermissionProvider { public const string Module = "EleWise.ELMA.CRMExtensions"; public const string CRMAccessPermissionId = "1958FB0F-755E-4C03-B94A-694B6E80333B"; public static readonly Permission CRMAccessPermission = new Permission(CRMAccessPermissionId, SR.T("Доступ к модулю"), "", SR.T("Работа с клиентами"), moduleUid: Module); public const string ViewCompanyPermissionId = "243C5DBA-ED64-4417-919A-2F20893F5017"; public static readonly Permission ViewCompanyPermission = new Permission(ViewCompanyPermissionId, SR.T("Просмотр компании"), "", SR.T("Работа с клиентами"), moduleUid: Module, //Тут задается ключ для группировки по модулям permissionType: PermissionType.Instance, //Тип привилегии, в данном случае - на сущность @base: CommonPermissions.View, //Базовая привилегия entityType: InterfaceActivator.TypeOf<ICompany>()); //Тип сущности для данной привилегии public IEnumerable<Permission> GetPermissions() { return new[] { CRMAccessPermission, ViewCompanyPermission }; } public IEnumerable<PermissionStereotype> GetPermissionStereotypes() { return new[] { new PermissionStereotype(new[] { CRMAccessPermission, ViewCompanyPermission }, SecurityConstants.AllUsersGroupDescriptor), }; } public List<string> LocalizedItemsNames { get { return new List<string> { SR.T("Доступ к модулю"), SR.T("Просмотр компании") }; } } public List<string> LocalizedItemsDescriptions { get { return new List<string> { SR.T("Пользователи, обладающие этой привилегией, могут редактировать структуру дерева общих фильтров. Для предоставление полного доступа ко всем фильтрам необходимо дабавить глобальную привилегию \"Доступ ко всем фильтрам\"") }; } } public List<string> LocalizedItemsCategories { get { return new List<string> { SR.T("Работа с клиентами") }; } } }
На данном этапе работа закончена, текущий менеджер сущности удовлетворяет всем нашим условиям, уровни доступа сконфигурированы.
Можно переходить к созданию веб-модуля.