Выявление неактивных контрагентов

Руководителям отделов продаж часто бывает необходимо выявить неактивных долгое время контрагентов. Рассмотрим случай, когда необходимо создать следующее правило: активностью по контрагенту считать изменение полей в карточке контрагента: Описание, Телефон, E-mail. А также активностью считается добавление комментария, сделки, звонка, письма, встречи.

Предлагается 2 шага для решения этой задачи:

  1. Создадим перехватчики (listener) изменений контрагента и связанных объектов, перечисленных выше. Будем использовать для этого специально созданное поле Дата и время последней активности (LastDateTime).
  2. Создадим фильтр для отображения неактивных контрагентов.

Перехватчики срабатывают при действиях с базой данных. Нас будет интересовать изменение значений в списках (Телефонов, E-mail, Комментариев) и сущностях (Контрагент, Сделка). Результат перехвата – обновлённое поле LastDateTime и текущей датой и временем.

Пример сценария с использованием PublicAPI

Примечание
Актуальная информация по PublicAPI доступна по ссылке.
Внимание!
Сценарий, указанный ниже, актуален для версий системы ELMA до 3.12.1 включительно.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using EleWise.ELMA.API;
using EleWise.ELMA.Common.Models;
using EleWise.ELMA.ComponentModel;
using EleWise.ELMA.CRM.Models;
using EleWise.ELMA.Logging;
using EleWise.ELMA.Runtime.NH.Listeners;
using EleWise.ELMA.Runtime.Settings;
using NHibernate.Event;

Текст сценария:

[Component] 
        public class ReSaveContractor : EntityEventsListener
        {
            // Переопределённый метод для перехвата изменений в телефонах и email контрагентов
            public override void OnPreUpdateCollection(PreCollectionUpdateEvent @event)
            {
                var collection = @event.Collection;
                var collectionEntry = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection);
                var collectionEntries = collection.Entries(collectionEntry.LoadedPersister);
          
                foreach (var entry in collectionEntries)
                {
                    // Обработка списка измененных комментариев
                    if (entry is IComment)
                    {
                        var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Comments in (Id = {0})", (entry as IComment).Id));// Поиск по фильтру контрагента, по которому сделан комментарий
                        if (listKA.Count > 0)
                        {
                            saveLastDateTime(listKA.First().Id);
                            break;
                        }
          
                    }
                    // Обработка списка измененных Телефонов
                    if (entry is IPhone)
                    {
                        var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Phone in (Id = {0})", (entry as IPhone).Id));// Поиск по фильтру контрагента, по которому сделан звонок
                        {
                            saveLastDateTime(listKA.First().Id);
                            break;
                        }
          
                    }
                    // Обработка списка измененных Email
                    if (entry is IEmail)
                    {
                        Logger.Log.Error("--->" + (entry as IEmail).GetType().ToString());
                        var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Email in (Id = {0})", (entry as IEmail).Id));// Поиск по фильтру контрагента, по которому создано email взаимоотношение
                        if (listKA.Count > 0)
                        {
                            saveLastDateTime(listKA.First().Id);
                            break;
                        }
          
                    }           
          
                }
          
            }
        
            // событие изменение объекта/документа
            public override bool OnPreUpdate(PreUpdateEvent @event)
            {  
                if (@event.Entity is IContractor)  //  интерфейс объекта типа Контрагент
                {
                    var Kontragent = (IContractor)@event.Entity;  // приведение к типу                     
                    saveLastDateTime(Kontragent.Id);
                } 
                if (@event.Entity is ISale)  //  интерфейс объекта типа Сделка
                {
                    var SaleNew = (ISale)@event.Entity;
                    if (SaleNew.Contractor != null) // 
                    {
                        saveLastDateTime(SaleNew.Contractor.Id);
                    }
                }
                if (@event.Entity is IRelationshipCall)
                {
                    Logger.Log.Error("--->" + (@event.Entity as IRelationshipCall).GetType().ToString());
                    var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Relationships in (Id = {0})", (@event.Entity as IRelationshipCall).Id));
                    if (listKA.Count > 0)
                    {
                        saveLastDateTime(listKA.First().Id);
                    }
          
                }    
                if (@event.Entity is IRelationshipMail)
                {
                    Logger.Log.Error("--->" + (@event.Entity as IRelationshipMail).GetType().ToString());
                    var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Relationships in (Id = {0})", (@event.Entity as IRelationshipMail).Id));
                    if (listKA.Count > 0)
                    {
                        saveLastDateTime(listKA.First().Id);
                    }
          
                }
                if (@event.Entity is IRelationshipMeeting)
                {
                    Logger.Log.Error("--->" + (@event.Entity as IRelationshipMeeting).GetType().ToString());
                    var listKA = PublicAPI.CRM.Contractor.Find(string.Format("Relationships in (Id = {0})", (@event.Entity as IRelationshipMeeting).Id));
                    if (listKA.Count > 0)
                    {
                        saveLastDateTime(listKA.First().Id);
                    }
          
                }    
                return false; // возврат в норме
          
            }
            // Обновление даты и времени последней активности по контрагенту
            private void saveLastDateTime(long id)
            {
                var kExt = PublicAPI.CRM.Contact.Load(id) as IContractorConfigExt;
                kExt.LastDateTime = DateTime.Now;
            }
        }

Пример сценария без использования PublicAPI

Создадим объект Перехватчики и на вкладке Сценарии добавим следующие пространства имен:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using EleWise.ELMA.Common.Models;
using EleWise.ELMA.ComponentModel;
using EleWise.ELMA.CRM.Models;
using EleWise.ELMA.Logging;
using EleWise.ELMA.Model.Common;
using EleWise.ELMA.Model.Managers;
using EleWise.ELMA.Runtime.NH.Listeners;
using EleWise.ELMA.Runtime.Setting; using NHibernate.Event;

Текст сценария:

namespace EleWise.ELMA.ConfigurationModel.Scripts
{  
  /// <summary>
  /// Модуль сценариев объекта "Перехватчики"
  /// </summary>
  public class PerehvatchikiScripts : EleWise.ELMA.Model.Scripts.Entities.EntityScriptModule<IPerehvatchiki>
  {
     [Component] 
     public class ReSaveContractor : EntityEventsListener 
     {  
       // Переопределённый метод для перехвата изменений в телефонах и email контрагентов
       public override void OnPreUpdateCollection(PreCollectionUpdateEvent @event)
       {
         var collection = @event.Collection;
         var collectionEntry = @event.Session.PersistenceContext.GetCollectionEntry(@event.Collection);
         var collectionEntries = collection.Entries(collectionEntry.LoadedPersister);
         foreach (var entry in collectionEntries) 
         {
   // Обработка списка измененных комментариев
           if (entry is IComment)
           {
             Filter filter = new Filter();  
             filter.Query = string.Format("Comments in (Id = {0})",(entry as IComment).Id); // Запрос фильтра для поиска контрагента, по которому сделан комментарий
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null); // Поиск по фильтру
             if (listKA.Count > 0)
             {
               saveLastDateTime(listKA.First().Id);
               break;
             }
           }
   // Обработка списка измененных Телефонов
           if (entry is IPhone)
           {
             Filter filter = new Filter();
             filter.Query = string.Format("Phone in (Id = {0})",(entry as IPhone).Id); // Запрос фильтра для поиска контрагента, по которому сделан звонок
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null); // Поиск по фильтру
             {
               saveLastDateTime(listKA.First().Id);
               break;
             }         
           }
   // Обработка списка измененных Email
           if (entry is IEmail)
           {
             Logger.Log.Error("--->"+(entry as IEmail).GetType().ToString());
             Filter filter = new Filter();
             filter.Query = string.Format("Email in (Id = {0})",(entry as IEmail).Id); // Запрос фильтра для поиска контрагента, по которому создано email взаимоотношение
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null); // Поиск по фильтру
             if (listKA.Count > 0)
             {
               saveLastDateTime(listKA.First().Id);
               break;
             }
           }           
         }
       }
       
       // событие изменение объекта/документа
       public override bool OnPreUpdate(PreUpdateEvent @event) 
       {     
         if(@event.Entity is IContractor)  //  интерфейс объекта типа Контрагент
         {
    var Kontragent  = (IContractor)@event.Entity;  // приведение к типу                     
           saveLastDateTime(Kontragent.Id);
          } 
  if(@event.Entity is ISale)  //  интерфейс объекта типа Сделка
         {
           var SaleNew = (ISale)@event.Entity;
           if (SaleNew.Contractor != null ) // 
           {
             saveLastDateTime(SaleNew.Contractor.Id);
           }
         }
         if (@event.Entity is IRelationshipCall)
           {
             Logger.Log.Error("--->"+(@event.Entity as IRelationshipCall).GetType().ToString());
             Filter filter = new Filter();
             filter.Query = string.Format("Relationships in (Id = {0})",(@event.Entity as IRelationshipCall).Id);
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null);
             if (listKA.Count > 0)
             {
               saveLastDateTime(listKA.First().Id);               
             }         
           }    
           if (@event.Entity is IRelationshipMail)
           {
             Logger.Log.Error("--->"+(@event.Entity as IRelationshipMail).GetType().ToString());
             Filter filter = new Filter();
             filter.Query = string.Format("Relationships in (Id = {0})",(@event.Entity as IRelationshipMail).Id);
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null);
             if (listKA.Count > 0)
             {
               saveLastDateTime(listKA.First().Id);               
             }         
           }
           if (@event.Entity is IRelationshipMeeting)
           {
             Logger.Log.Error("--->"+(@event.Entity as IRelationshipMeeting).GetType().ToString());
             Filter filter = new Filter();
             filter.Query = string.Format("Relationships in (Id = {0})",(@event.Entity as IRelationshipMeeting).Id);
             var listKA = EntityManager<IContractor>.Instance.Find(filter, null);
             if (listKA.Count > 0)
             {
               saveLastDateTime(listKA.First().Id);
             }
            }    
 return false; // возврат в норме         
       }
       // Обновление даты и времени последней активности по контрагенту
       private void saveLastDateTime(long id)
       {
           var kExt = EntityManager<IContractorConfigExt>.Instance.Load(id); // загрузить расширенную модель для контрагента
           kExt.LastDateTime = DateTime.Now;
       }       
    }   
  }
}
  1. Опубликуем объект и перезапустим сервер. Добавим, например, комментарий по контрагенту, чтобы заполнилось поле LastDateTime.
  2. Создадим фильтр в контрагентах для поиска контрагентов, по которым не было активности за последние две недели.

Откройте расширенный поиск, выберите EQL и напишите следующий код:

(NOT LastActiveTime in RelativeDateTime(’-2н’, ’0н’)) OR (LastActiveTime is NULL)

После поиска у нас должны появится все контрагенты, за исключением тех, у кого происходило изменение полей в карточке контрагента: Описание, Телефон, E-mail. Или добавление комментария, сделки, звонка, письма, встречи.

Можно создать фильтр, чтобы отслеживать активность по контрагентам за сегодня:

LastActiveTime >= DateTime(’Today’)