Creatio development guide
PDF
Разработка в Creatio на примерах
Это документация Creatio версии 7.16.0. Мы рекомендуем использовать новую версию документации.

Добавление правила поиска дублей при сохранении записи

Glossary Item Box

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

Описанный процесс добавления правила поиска дублей актуален для Creatio версий 7.13.2 и ниже. Для версий системы 7.13.4 и выше функциональность поиска дублей описана в статье “Поиск и объединение дублей”, а работа с правилами массового поиска дублей — в статье "Добавление правила массового поиска дублей".

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

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

  1. Выполнить замещение схемы DuplicatesSearchUtilitiesV2.
  2. Создать класс UsrSingleRequest.
  3. Добавить класс UsrSingleRequesListener.
  4. Создать класс UsrDeduplicationProcessing.
  5. Скомпилировать и перезапустить приложение.
  6. Создать пользовательский сервис.
  7. Заместить методы getDuplicatesServiceName и getFindDuplicatesServiceMethodNamе.
  8. Удалить хранимые процедуры из базы данных.
  9. Выполнить скрипт по удалению типа CreatingObjectInfo.
  10. Создать хранимую процедуру tsp_FindDuplicate.
  11. Выполнить установку удаленных хранимых процедур.
  12. Добавить хранимую процедуру tsp_FindAccountDuplicateByInn.

Описание примера

Реализовать отработку пользовательского правила поиска дублей при сохранении записи для объекта [Account].

Алгоритм реализации примера

1. Заместите схему DuplicatesSearchUtilitiesV2

В пользовательской схеме заместите метод getDataForFindDuplicatesService(), добавив UsrINN аналогично "Name". Процесс замещения схемы подробно описан в статье "Архитектурные элементы конфигурации".

Исходный код представлен ниже.

getDataForFindDuplicatesService: function() {
    var communication = this.getCommunications();
    val email = this.get("Email");
    if (!this.Ext.isEmpty(email)) {
        communication.push({
            "Number": email,
            "CommunicationTypeId": ConfigurationConstants.CommunicationTypes.Email
        });
    }
    var data = {
        schemaName: this.entitySchemaName,
        request: {
            Id: this.get("Id"),
            Name: this.get("Name"),
            UsrINN: this.get("UsrINN"),
            AlternativeName: this.get("AlternativeName"),
            Communication: communication
        }
    };
    return data;
},

2. Создайте класс UsrSingleRequest

Класс UsrSingleRequest унаследуйте от класса SingleRequest схемы SearchDuplicatesService. В классе UsrSingleRequest добавьте пользовательское свойство UsrINN.

Исходный код представлен ниже.

namespace Terrasoft.Configuration.SearchDuplicatesService {
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.ServiceModel.Activation;
    using System.Web;
    using Terrasoft.Common;
    using Terrasoft.Core;
    using Terrasoft.Core.DB;
    using Terrasoft.Core.Entities;
    using Terrasoft.Core.Scheduler;
    using System;
    using System.Data;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Xml;
    using Quartz;
    using Quartz.Impl.Triggers;
    using Column = Terrasoft.Core.DB.Column;
    
    [DataContract]
    public class UsrSingleRequest: SingleRequest {
        [DataMember]
        public string UsrINN { get; set; }
    }
}

3. Добавьте класс UsrSingleRequesListener

Добавьте класс UsrSingleRequesListener, который будет заменять вызов SingleRequest на UsrSingleRequest. Класс UsrSingleRequesListener должен реализовывать интерфейс IAppEventListener. В метод OnAppStart добавьте ClassFactory.Bind().

Исходный код представлен ниже.

namespace Terrasoft.Configuration
{
    using Terrasoft.Core.Factories;
    using Terrasoft.Web.Common;
    using Terrasoft.Configuration.SearchDuplicatesService;
    
    #region Class: UsrSingleRequestListener
    
    public class UsrSingleRequestListener: IAppEventListener
    {
        #region Methods: Public
        
        public void OnAppStart(AppEventContext context) {
            ClassFactory.Bind<SingleRequest, UsrSingleRequest>();
        }
        
        public void OnAppEnd(AppEventContext context) {
        }
        
        public void OnSessionStart(AppEventContext context) {
        }
        
        public void OnSessionStart(AppEventContext context) {
        }
        
        #endregion
    }
    
    #endregion
}

4. Создайте класс UsrDeduplicationProcessing

Создайте класс UsrDeduplicationProcessing, унаследованный от схемы DeduplicationProcessing. В созданном классе выполните следующие действия:

  1. Добавьте методы AddElementsToRow и GetPreparedXml схемы SearchDuplicatesService, изменив их названия на UsrAddElementsToRow и UsrGetPreparedXml.
  2. В метод UsrAddElementsToRow добавьте UsrINN.
  3. В методе UsrGetPreparedXml измените вызов AddElementsToRow на UsrAddElementsToRow.

    Исходный код представлен ниже.

    private XmlDocument UsrGetPreparedXml(UsrSingleRequest request) {
        XmlDocument xml = new XmlDocument();
        XmlElement elementRows = xml.CreateElement("rows");
        List<RequestCommunication> communicationsList = request.Communication && new List<RequestCommunication>();
        foreach (RequestCommunication communication in communicationsList) {
            XmlElement elementRow = xml.CreateElement("row");
            XmlElement elementCommunicationTypeId = xml.CreateElement("CommunicationTypeId");
            elementCommunicationTypeId.InnerText = communication.CommunicationTypeId.ToString();
            XmlElement elementNumber = xml.CreateElement("Number");
            elementNumber.InnerText = communication.Number;
            elementRow.AppendChild(elementCommunicationTypeId);
            elementRow.AppendChild(elementNumber);
            UsrAddElementsToRow(xml, elementRow, request);
            elementRows.AppendChild(elementRow);
        }
        if (communicationsList.Count < 1) {
            XmlElement elementRow = xml.CreateElement("row");
            UsrAddElementsToRow(xml, elementRow, request);
            elementRows.AppendChild(elementRow);
        }
        xml.AppendChild(elementRows);
        return xml;
    }
    
    private void UsrAddElementsToRow(XmlDocument xml, XmlElement elementRow, UsrSingleRequest request) {
        XmlElement elementName = xml.CreateElement("Name");
        ele.InnerText = request.Name;
        elementRow.AppendChild(elementName);
        XmlElement elementUsrINN = xml.CreateElement("UsrINN");
        elementUsrINN.InnerText = request.UsrINN;
        elementRow.AppendChild(elementUsrINN);
        if (request Id != Guid Empty) {
            XmlElement elementId = xml.CreateElement("Id");
            elementId.InnerText = request.Id.ToString();
            elementRow.AppendChild(elementId);
        }
    }
    
  4. Переопределите метод FindDuplicates.
  5. Замените GetPreparedXml на UsrGetPreparedXml.
  6. Приведите передаваемый в UsrGetPreparedXml параметр data к типу UsrSingleRequest.
  7. В методах UsrAddElementsToRow и UsrGetPreparedXml измените тип параметра request с SingleRequest на UsrSingleRequest.

    Исходный код представлен ниже.

    public override List<Guid> FindDuplicates(string schemaName, SingleRequest data) {
        XmlDocument xml = UsrGetPreparedXml((UsrSingleRequest)data);
        return FindDuplicates(schemaName, xml);
    }
    
  8. Добавьте конструктор с параметром и вызовите базовую реализацию конструктора.

5. Скомпилируйте и перезапустите приложение

После выполнения пунктов 1-4 скомпилируйте приложение, а потом обязательно его перезапустите.

6. Создайте пользовательский сервис

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

  1. Скопируйте метод FindDuplicatesOnSave из схемы DeduplicationService.
  2. Подставьте UsrDeduplicationProcessing вместо DeduplicationProcessing.

    Исходный код представлен ниже.

    namespace Terrasoft.Configuration
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.Data;
        using System.Linq;
        using System.Runtime.Serialization;
        using System.Xml;
        using Terrasoft.Common;
        using Terrasoft.Configuration.RightsService;
        using Terrasoft.Core;
        using Terrasoft.Core.DB;
        using Terrasoft.Core.Entities;
        using Terrasoft.Core.Factories;
        using Terrasoft.Core.Scheduler;
        using Terrasoft.Nui.ServiceModel.Extensions;
        using Terrasoft.Configuration.SearchDuplicatesService;
        using EntityCollection = Terrasoft.Nui.ServiceModel.DataContract.EntityCollection;
        
        public class UsrDeduplicationProcessing: DeduplicationProcessing
        {
            public UsrDeduplicationProcessing(UserConnection userConnection): base(userConnection)
            {
                
            }
    

7. Заместите методы getDuplicatesServiceName и getFindDuplicatesServiceMethodNamе

В схеме AccountPageV2 пакета Deduplication есть методы getDuplicatesServiceName и getFindDuplicatesServiceMethodName. Заместите эти методы и возвращайте в них название пользовательского сервиса и название метода FindDuplicatesOnSave пользовательского сервиса.

8. Удалите хранимые процедуры из базы данных

Удалите из базы данных все хранимые процедуры, связанные с поиском дублей (они все начинаются на Find).

9. Выполните скрипт по удалению типа CreatingObjectInfo

Выполните скрипт по удалению типа CreatingObjectInfo, который создается в tsp_FindDuplicate и используется во всех хранимых процедурах по поиску дублей. Для этого выполните следующий SQL-запрос:

IF TYPE_ID('[dbo].[CreatingObjectInfo]') IS NOT NULL
BEGIN
    drop type [CreatingObjectInfo];
END

10. Создайте хранимую процедуру tsp_FindDuplicate

Создайте пользовательскую хранимую процедуру tsp_FindDuplicate. В созданной процедуре выполните следующие действия:

  1. Создайте тип CreatingObjectInfo, добавив в него UsrINN. Для этого выполните следующий SQL-запрос:
    ]IF TYPE_ID('[dbo].[CreatingObjectInfo]') IS NULL
    ]BEGIN
    ]    CREATE TYPE CreatingObjectInfo AS TABLE (
            Id NVARCHAR(36),
            ObjectModifiedOn NVARCHAR(128),
            CommunicationTypeId NVARCHAR(36),
            CityId NVARCHAR(36),
            Name NVARCHAR(128),
            UsrINN NVARCHAR(50),
            Number NVARCHAR(250),
            SearchNumber NVARCHAR(250),
            Web NVARCHAR(250)
        );
    END;
    GO    
    
  2. Добавьте UsrINN в @parsedConfig. Для этого выполните следующий SQL-запрос:
    IF @xmlRows <> ''
    BEGIN
        SET @minimumGroupCount = 0;
        SET @xmlRowsConfig = CAST(@xmlRows AS XML);
        INSERT INTO @parsedConfig
        SELECT
            NULLIF(b.value('(./Id/text())[1]', 'NVARCHAR(36)'), NEWID()) AS [Id],
            NULLIF(b.value('(./ContactModifiedOn/text())[1]', 'NVARCHAR(128)'), AS [ObjectModifiedOn],
            NULLIF(b.value('(./CommunicationTypeId/text())[1]', 'NVARCHAR(36)'), AS [CommunicationTypeId],
            NULL AS [CityId],
            NULLIF(b.value('(./Name/text())[1]', 'NVARCHAR(128)'), AS [Name],
            NULLIF(b.value('(./UsrINN/text())[1]', 'NVARCHAR(50)'), AS [UsrINN],
            [dbo].[fn_NormalizeString](NULLIF(b.value('(./Number/text())[1]', 'NVARCHAR(250)'), ''),N'0-9a-za-я@_.') AS [Number],
            [dbo].[fn_ExtractDigitLimitFromNumber](LTRIM(
                [dbo].[fn_GetPhoneNumberSearchForm](NULLIF(b.value('(./Number/text())[1]', 'NVARCHAR(250)'), ''))
            )) AS [SearchNumber],
            NULLIF([dbo].[fn_ExtractDomainFromUrl](b.value('((./Number/text())[1]', 'NVARCHAR(250)')), '') AS [Web]
        FROM @xmlRowsConfig.nodes('/rows/row') as a(b);
        SET @processingRowId = (SELECT TOP 1 Id FROM @parsedConfig);
    END;        
    
  3. Установите в базе данных tsp_FindDuplicate.

11. Выполните установку удаленных хранимых процедур

Выполните установку в базе данных всех хранимых процедур, которые были удалены из базы данных как описано в пункте 9.

12. Добавьте хранимую процедуру tsp_FindAccountDuplicateByInn

Добавьте пользовательскую хранимую процедуру tsp_FindAccountDuplicateByInn, в которой добавьте блок ELSE при добавлении записей в #searchAccount. Для этого выполните следующий SQL-запрос:

IF @parsedConfigRowsCount = 0
BEGIN
    INSERT INTO #searchAccount ([Name], [SortDate])
    SELECT
        [dedup].[Name],
        MAX([dedup].[SortDate]) [SortDate]
    FROM (
        SELECT [Id]
            [dbo].[fn_NormalizeString]([Name], @validChar) AS [Name],
            MAX([ModifiedOn]) [SortDate]
        FROM [VmAccountCleanDataValues] WITH (NOEXPAND)
        GROUP BY [Id], [Name]
    ) AS [dedup]
    GROUP BY [dedup], [Name]
    HAVING COUNT(*) > 1;
END;
ELSE
BEGIN
    INSERT INTO #searchAccount ([Name], [SortDate])
    SELECT
        [dbo].[fn_NormalizeString]([Name], @validChar) AS [Name],
        GETDATE() AS [SortDate]
    FROM @parsedConfig
END;

Установите в базе данных tsp_FindAccountDuplicateByInn.

© Terrasoft 2002-2020.

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

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