Разработка
30
Мар
3

«Мертвые души»

Некоторым компаниям приходится работать с очень и очень большими наборами данных, в том числе и большим количеством учетных записей клиентов. Но, не все эти «учетные записи» являются клиентами на самом деле: т.е. существуют на данный момент, занимаются тем же бизнесом или не работают с Вашими конкурентами и т.д.

Если верить правилу Парето, то 20% усилий дают 80% результата. А если тратить усилия на «мертвых» клиентов, то особого результата не будет 🙂 Поэтому базу клиентов необходимо время от времени зачищать 🙂 дабы не отвлекать Ваш персонал лишней информацией.

Как определить что клиент не активный? Например, по нему не было ни одной активности за длительное время. Возьмем это за основу и попробуем его автоматически деактивировать… А делать это мы будем с помощью кастомного бизнес-процесса:

  • Создайте новый бизнес-процесс в Visual Studio и повесьте на него такой код:
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Collections;
    using System.Drawing;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.ComponentModel.Serialization;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.Runtime;
    using System.Workflow.Activities;
    using System.Workflow.Activities.Rules;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.SdkTypeProxy;
    using Microsoft.Crm.Workflow;
    using Microsoft.Crm.Workflow.Activities;
    using System.Data.SqlClient; 
    
    namespace MaintenanceWorkflow
    {
        // Задаем имя (отображаемое на форме) кастомного шага бизнес-процесса
        [CrmWorkflowActivity("Зачистка базы")]
    
        public partial class AccountMaintenanceWorkflow : SequenceActivity
        {
            // Переопределеяем метод Execute
            protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
            {
                // Настраиваем CRM Service через контекст сервиса
                IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
                IWorkflowContext context = contextService.Context;
                ICrmService crmService = context.CreateCrmService();
    
                // Строка подключания с базе данных MS CRM
                string connectionString = "Data Source = mmcrm.ru; Initial Catalog = superfirma_MSCRM; Integrated Security = SSPI;";
    
                // Подключаемся к SQL серверу используя строку подключения
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand comm = conn.CreateCommand();
    
                    // Выполняем SQL-команду под определенным пользователем
                    comm.CommandText = @"Execute as Login='D2008\Administrator'; ";  
    
                    // SQL команда: запрашиваем GUID'ы Бизнес-партнеров либо не имеющих Действий за последний год, либо вообще не имеющих действий
                    comm.CommandText += "select RegardingObjectId GUID from FilteredActivityPointer ";
                    comm.CommandText += "where RegardingObjectTypeCode = 1 and not ModifiedOn > dbo.fn_LastXYear(getdate(),1) and StatusCode = 1 ";
                    comm.CommandText += "UNION ";
                    comm.CommandText += "select AccountId from FilteredAccount ";
                    comm.CommandText += "where AccountId NOT IN(select RegardingObjectId from ActivityPointer where RegardingObjectTypeCode = 1) and StatusCode = 1";
                    
                    // Возвращаем контекст обратно к Network Service
                    comm.CommandText += "revert;";
    
                    // Выполняем SQL запрос
                    comm.CommandType = System.Data.CommandType.Text;
                    SqlDataReader myReader = comm.ExecuteReader();
    
                    // Задаем статус записей, которые хотим деактивировать
                    AccountStateInfo accStateInfo = new AccountStateInfo();
                    accStateInfo.Value = AccountState.Inactive;
                    
                    // Просматриваем каждый возвращенный GUID и ...
                    while (myReader.Read())
                    {
                        // ... добавляем к записям Примечания
                        annotation note = new annotation();
                        note.subject = "Деактивация записи";
                        note.notetext = "Эта запись была деактивирована за ненадобностью " + DateTime.Now.ToShortDateString();
                        note.objectid = new Lookup();
                        note.objectid.type = EntityName.account.ToString();
                        note.objectid.Value = new Guid(myReader["GUID"].ToString());
                        note.objecttypecode = new EntityNameReference();
                        note.objecttypecode.Value = "account";
                        crmService.Create(note);
    
                        // ... деактивируем запись Бизнес-партнера
                        SetStateAccountRequest accStatus = new SetStateAccountRequest();
                        accStatus.AccountState = AccountState.Inactive;
                        accStatus.AccountStatus = -1;
                        accStatus.EntityId = new Guid(myReader["GUID"].ToString());
                        crmService.Execute(accStatus);
                    }
                    myReader.Close();
                }
    
                return ActivityExecutionStatus.Closed;
            }
        }
    }
    

    Этот код делает три вещи: запрашивает (напрямую в SQL Server’е) все записи Бизнес-партнера, у которых либо нет связанный Деййствий, либо они не изменялись в течение прошлого года. Затем просматриваем возвращенные записи и создаем для каждой из них Примечание с текущей датой (т.е. датой деактивации), а затем деактивируем саму запись Бизнес-партнера.

  • Зарегистрируйте сборку с помощью Plugin Registration Tool;
  • Создайте новый (настроечный) объект. Запись этого объекта мы будем использовать для запуска бизнес-процесса;
  • Создайте новый бизнес-процес в CRM в отношении настроечного объекта. Добавьте в него только одни шаг – тот, что мы только что напрограммировали 🙂
  • Создайте новую запись настроечного объекта и запустите в ее отношении созданный ранее бизнес-процесс. Через небольшое время можете смотреть на деактивированные записи Бизнес-партнера.





А чтобы данная зачистка выполнялась регулярно, то воспользуйтесь одни из следующих способов для периодического запуска бизнес-процесса: Period Workflow Tool или Периодическое выполнение бизнес-процессов, эпизод II.

Комментарии (3)
  • V©R©N 30.03.2010

    между 84-й и 85-й строкой кода нужно вставить
    myReader.Close();

  • slivka_83 30.03.2010

    Спасибо, добавил 🙂

  • V©R©N 30.03.2010

    Немножко не туда 🙂
    После закрывающей фигурной скобки блока while, т.е. в текущей версии примера кода после скобки находящейся в 85-й строке.

*

code