Документация по разработке bpm’online
PDF
Использование EntityMapper

Glossary Item Box

Общие сведения

Класс Terrasoft.Configuration.EntityMapper — это утилитный класс конфигурации, который реализован в схеме EntittyMapper пакета [FinAppLending] продукта Lending. EntittyMapper позволяет сопоставлять данные одной сущности (Entity) с другой сущностью по правилам, определенным в конфигурационном файле. Использование подхода сопоставления данных разных сущностей позволяет избежать появления однообразного кода.

В продукте Lending существует два объекта, содержащих одинаковые колонки. Это объекты [Физ. лицо] ([Contact]) и [Анкета] ([AppForm]). Также существует несколько деталей, относящихся к объекту [Физ. лицо] ([Contact]) и имеющих похожие детали, относящиеся к [Анкета] ([AppForm]). Очевидно, что при заполнении анкеты должна быть возможность по колонке [Id] объекта [Физ. лицо] ([Contact]) получить список всех его колонок и значений, а также список нужных деталей с их колонками и значениями, и сопоставить эти данные с данными, связанными с анкетой. После этого можно автоматически заполнить поля анкеты сопоставленными данными. Таким образом можно существенно уменьшить затраты на ручной ввод одинаковых данных.

Описание кейса

Для проверки механизма сопоставления данных с помощью Terrasoft.Configuration.EntityMapper необходимо создать пользовательский класс UsrEntityMapperConfigsContainer. В этом классе нужно реализовать логику настройки сопоставления данных объектов [Физ. лицо] ([Contact]) и [Анкета] ([AppForm]). Чтобы вызывать выполнение сопоставления со стороны клиентской части приложения, нужно реализовать пользовательский конфигурационный сервис. В профиль страницы редактирования необходимо анкеты добавить кнопку, которая будет вызывать пользовательский конфигурационный сервис и выводить результат в консоль браузера.

Алгоритм реализации кейса

1. Создать пользовательский класс сопоставления данных UsrEntityMapperConfigsContainer

Создание схемы [Исходный код]подробно описано в статье "Создание схемы [Исходный код]".

Для созданной схемы необходимо установить следующие значения свойств:

  • [Заголовок] ([Title]) — "UsrEntityMapperConfigsContainer".
  • [Название] ([Name]) — "UsrEntityMapperConfigsContainer".
  • [Пакет] ([Package]) — "Custom" (или другой пользовательский пакет).

На вкладку [Исходный код] схемы необходимо добавить следующий код:

namespace Terrasoft.Configuration
{
    using System;
    using System.Collections.Generic;
// Класс содержит настройки сопоставления.
public class UsrEntityMapperConfigsContainer
{
    // Настройки сопоставления контакта и анкеты.
    public MapConfig ContactToAppFormConfig { get; protected set; }

    public UsrEntityMapperConfigsContainer() {
        this.InitContactToAppFormConfig();
    }
    // Выполняет настройку сопоставления контакта и анкеты.
    protected virtual void InitContactToAppFormConfig() {
        var columns = new Dictionary<string, string>();
        // В данном случае названия колонок контакта и анкеты совпали.
        columns.Add("Surname", "Surname");
        columns.Add("GivenName", "GivenName");
        columns.Add("MiddleName", "MiddleName");
        columns.Add("INN", "INN");
        columns.Add("SpouseSurname", "SpouseSurname");
        columns.Add("SpouseGivenName", "SpouseGivenName");
        columns.Add("SpouseMiddleName", "SpouseMiddleName");
        columns.Add("Spouse", "Spouse");
        var config = new MapConfig {
            SourceEntityName = "Contact",
            Columns = columns,
            RelationEntities = new List<RelationEntityMapConfig>() {
                    new RelationEntityMapConfig() {
                        SourceEntityName = "Contact",
                        ParentColumnName = "Spouse",
                        Columns = new Dictionary<string, string>() {
                            { "Surname", "SpouseSurname" },
                            { "BirthDate", "SpouseBirthDate" }
                        }
                    }
                },
                DetailsConfig = new List<DetailMapConfig>() {
                    new DetailMapConfig() {
                        SourceEntityName = "ContactAddress",
                        DetailName = "RegistrationAddressFieldsDetail",
                        Columns = new Dictionary<string, string>() {
                            { "AddressType", "AddressType" },
                            { "Country", "Country" },
                            { "Region", "Region" }
                        },
                        Filters = new List<EntityFilterMap>() {
                            new EntityFilterMap(){
                                ColumnName = "AddressType",
                                Value = BaseFinanceConst.RegistrationAddressTypeId
                            }
                        }
                    }
                },
                CleanDetails = new List<string>() {
                    "AppFormIncomeDetail"
                }
            };
            this.ContactToAppFormConfig = config;
        }
    }
}

После внесения изменений схему необходимо опубликовать.

2. Создать пользовательский конфигурационный сервис сопоставления данных

Создание пользовательского конфигурационного сервиса подробно описано в статье "Как создать свой конфигурационный сервис".

Для этого необходимо в пользовательском пакете создать схему [Исходный код] ([Source Code]). Для созданной схемы необходимо установить следующие значения свойств:

  • [Заголовок] ([Title]) — "UsrEntityMappingService".
  • [Название] ([Name]) — "UsrEntityMappingService".
  • [Пакет] ([Package]) — "Custom" (или другой пользовательский пакет).

На вкладку [Исходный код] схемы необходимо добавить следующий код:

namespace Terrasoft.Configuration
{
using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using Terrasoft.Core;
using Terrasoft.Core.Factories;
using Terrasoft.Core.Entities;
using Terrasoft.Common;
using System.Web;
using Terrasoft.Web.Common;
using Terrasoft.Nui.ServiceModel.DataContract;
using Terrasoft.Common.Json;
using Terrasoft.Core.Configuration;

    /// Класс сервиса сопоставления сущностей и их деталей.
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class UsrEntityMappingService: BaseService
    {
        private EntityMapper _entityMapper;
        // Возвращает экземпляр EntityMapper.
        protected virtual EntityMapper EntityMapper {
            get {
                return _entityMapper ?? (_entityMapper = ClassFactory.Get<EntityMapper>(
                    new ConstructorArgument("userConnection", this.UserConnection)));
            }
        }
        // Возвращает настройки сопоставления.
        protected virtual MapConfig GetConfig() {
            UsrEntityMapperConfigsContainer mapperConfigsContainer = new UsrEntityMapperConfigsContainer();
            return mapperConfigsContainer.ContactToAppFormConfig;
        }
        // Выполняет сопоставление и возвращает результат. Основной метод сервиса.
        [OperationContract]
        [return: MessageParameter(Name = "result")]
        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,
            RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public EntityMappingResult GetMappedEntity(string id)
        {
            EntityMappingResult result = new EntityMappingResult();
            try {
                Guid recordId;
                MapConfig config = this.GetConfig();
                EntityResult entityResult = new EntityResult(config);
                result.columns = entityResult.Columns;
                result.details = entityResult.Details;
                if (!Guid.TryParse(id, out recordId)) {
                    return result;
                }
                entityResult = EntityMapper.GetMappedEntity(recordId, config);
                result.columns = entityResult.Columns;
                result.details = entityResult.Details;
                result.Success = true;
            } catch (Exception e){
                result.Success = false;
                result.Exception = e;
            }
            return result;
        }
    }

}

После внесения изменений схему необходимо опубликовать.

3. Добавить кнопку вызова сервиса на странице редактирования заявки

Для этого необходимо заместить существующую схему [Страница редактирования анкеты по заявке] ([Application Form Edit Page]). Замещение клиентских схем подробно описано в статье "Создание клиентской схемы".

В замещающей схеме нужно добавить локализуемую строку (рис. 1) со следующими свойствами:

  • [Заголовок] ([Title]) — "Вызвать сервис" ("Call service").
  • [Название] ([Name]) — "EntityMappingButtonCaption".

Рис. 1. — Добавление локализуемой строки

На вкладку [Исходный код] схемы необходимо добавить следующий код:

define("AppFormPage", [], function() {
    return {
        entitySchemaName: "AppForm",
        methods: {
            // Функция запроса к пользовательскому сервису.
            requestContactData2: function() {
                var data = {
                    id: this.get("Contact").value
                };
                // Конфигурационный объект для передачи параметров сервису.
                var config = {
                    serviceName: "UsrEntityMappingService",
                    methodName: "GetMappedEntity",
                    data: data
                };
                // Вызов сервиса.
                this.callService(config, this.parseMappedEntityResponse2, this);
            },
                //Callback-функция для вывода ответа от сервиса в консоль.
            parseMappedEntityResponse2: function(response) {
                window.console.log("Ответ от UsrEntityMappingService", response);
            }
        },
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "insert",
                "parentName": "ProfileContainer",
                "propertyName": "items",
                "name": "EntityMappingButton",
                "values": {
                    itemType: Terrasoft.ViewItemType.BUTTON,
                    "style": Terrasoft.controls.ButtonEnums.style.GREEN,
                    // Привязка заголовка кнопки к локализуемой строке схемы.
                    caption: { bindTo: "Resources.Strings.EntityMappingButtonCaption" },
                    // Привязка метода-обработчика нажатия кнопки.
                    click: { bindTo: "requestContactData2" },
                    "layout": {
                        "column": 0,
                        "row": 2,
                        "colSpan": 24
                    }
                }
            }
        ]/**SCHEMA_DIFF*/
    };
});

Здесь в массив diff добавляется конфигурационный объект, с помощью которого в профиль страницы редактирования заявки добавляется кнопка. При нажатии на кнопку вызывается метод requestContactData2(), в котором выполняется вызов пользовательского конфигурационного сервиса UsrEntityMappingService с необходимыми параметрами. После получения ответа от сервиса выполняется вызов сallback-функции parseMappedEntityResponse2(), которая и выводит в консоль браузера ответ от сервиса.

ВАЖНО

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

После внесения изменений схему необходимо сохранить.

В результате выполнения кейса на странице редактирования анкеты появится кнопка, после нажатия на которую в консоли браузера будет выведен объект с сопоставленными данными (рис. 2).

Рис. 2. — Результат выполнения кейса

ВАЖНО

Если страница редактирования анкеты открыта в режиме новой записи, то необходимо предварительно выбрать или создать контакт, связанный с создаваемой анкетой. Если контакт не будет выбран, возникнет исключение, т.к. this.get("Contact") вернет null.

© Terrasoft 2002-2019.

Был ли данный материал полезен?

Как можно улучшить эту статью?