[ELMA3] Выявление неактивных контрагентов
Руководителям отделов продаж часто бывает необходимо выявить неактивных долгое время контрагентов. Рассмотрим случай, когда необходимо создать следующее правило: активностью по контрагенту считать изменение полей в карточке контрагента: Описание, Телефон, E-mail. А также активностью считается добавление комментария, сделки, звонка, письма, встречи.
Предлагается 2 шага для решения этой задачи:
- Создадим перехватчики (listener) изменений контрагента и связанных объектов, перечисленных выше. Будем использовать для этого специально созданное поле Дата и время последней активности (LastDateTime).
- Создадим фильтр для отображения неактивных контрагентов.
Перехватчики срабатывают при действиях с базой данных. Нас будет интересовать изменение значений в списках (Телефонов, E-mail, Комментариев) и сущностях (Контрагент, Сделка). Результат перехвата – обновлённое поле LastDateTime и текущей датой и временем.
Пример сценария с использованием PublicAPI
Для корректной работы сценария необходимо подключить следующие пространства имен:
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
Создадим объект Перехватчики и на вкладке Сценарии добавим следующие пространства имен:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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; |
Текст сценария:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 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; } } } } |
- Опубликуем объект и перезапустим сервер. Добавим, например, комментарий по контрагенту, чтобы заполнилось поле LastDateTime.
- Создадим фильтр в контрагентах для поиска контрагентов, по которым не было активности за последние две недели.
Откройте расширенный поиск, выберите EQL и напишите следующий код:
(NOT LastActiveTime in RelativeDateTime(’-2н’, ’0н’)) OR (LastActiveTime is NULL)
После поиска у нас должны появится все контрагенты, за исключением тех, у кого происходило изменение полей в карточке контрагента: Описание, Телефон, E-mail. Или добавление комментария, сделки, звонка, письма, встречи.
Можно создать фильтр, чтобы отслеживать активность по контрагентам за сегодня:
LastActiveTime >= DateTime(’Today’)