CRM 4.0 - Znikające terminy w Outlook

W większości firm Outlook jest strategicznym narzędziem pracy handlowców. To tam rejestrowane jest to co handlowiec robi, z kim się spotyka, itd.

Po wdrożeniu CRM w organizacji zazwyczaj instalowany jest na większości komputerów dodatek do programu Outlook, który pozwala na pracę w CRM w oknie outlook, śledzenie elementów outlookowych bezpośrednio w CRM. Wśród takich elementów jest oczywiście zaproszenie na spotkanie. Jednakże z tym elementem jest bardzo dużo problemów, gdyż w CRM 4.0 nie ma czegoś takiego jak zaproszenie na spotkanie. Prześledźmy następujący scenariusz:

  1. Użytkownik CRM (nazwijmy go Organizator 1) tworzy zaproszenie na spotkanie i wysyła go do użytkownika (nazwijmy go Handlowiec 1). Zaproszenie to nie jest śledzone w CRM.
  2. Handlowiec 1 dostaje zaproszenie, wybiera opcję “Śledź w programie CRM”. Powoduje to powstanie w CRM rekordu Termin, gdzie Właścicielem jest Handlowiec 1, natomiast Organizatorem jest Organizator 1.
    1. Jeśli w CRM Handlowiec 1 miał ustawiony adres email to po otwarciu terminu w CRM w polu wymagani uczestnicy zostanie zaprezentowane wskazanie na użytkownika. W tym przypadku po przeprowadzeniu synchronizacji w programie Outlook (CRM –> Synchronizuj z CRM) termin nie zniknie z kalendarza użytkownika w Outlook
    2. Jeśli w CRM Handlowiec 1 nie miał ustawionego adresu email to po otwarciu terminu w CRM w polu wymaganie uczestniczy widoczny będzie czerwony adres email z informację, że system CRM nie był w stanie rozpoznać uczestnika. W tym przypadku po przeprowadzeniu synchronizacji termin w kalendarzu w Outlook zostanie usunięty. Jedyna możliwość przywrócenia tego terminu do kalendarza Outlook jest wykonanie operacji:
      1. Otwarcie rekordu użytkownika i uzupełnienie mu adresu email
      2. Otwarcie terminu w CRM i wskazanie jaki użytkownik krył się pod tym adresem email
      3. Przeprowadzenie ponownej synchronizacji w Outlook.

Zachęcam do przeprowadzenia testów kiedy zaproszenie jest wysyłane do większej liczby użytkowników niż jeden :). Kilka scenariuszy przeprowadził Kuba i opisał to na swoim blogu: http://crmblog.pl/2009/09/17/co-dzieje-sie-z-rekordami-po-synchronizacji-crm-outlook/

SetParent – czyli jak napisać plugin do tej wiadomości

Przy okazji rozbudowania funkcjonalności CRM4.0 potrzebowałem napisać plugin, którego zadaniem będzie wykonanie pewnej operacji w trakcie kiedy zmieni się Menedżer użytkownika.

Dla przypomnienia: Pole Menedżer jest widoczne na formatce użytkownika jednakże ustawienie jego wartości jest możliwe tylko i wyłączenie poprzez skorzystanie z funkcjonalności ukrytej w menu Akcje lub też wykonanie kodu związane z klasą SetParentSystemUserRequest:

image

Okazuje się, że narzędzie Plugin Registration Tool (PRT) nie udostępnia nam możliwości podłączenia się pod zdarzenie związane ze zmianą interesującego nas pola. Interesujące nas wiadomości nazywa się SetParent.

Nie ma jednak tego ukrytego co by odkryte może zostać i okazuje się, że w bazie danych CRM taką wiadomość można odkryć. Jak ?

Wszystkie wiadomości jakie CRM może przetwarzać są zapisane w tabeli SdkMessageBase. Jak wykonamy sobie następujące zapytanie SQL:

select * from SdkMessageBase where Name = 'SetParent'

Zobaczymy, że tabela zwróci nam jeden rekord. To co jest dla nas z tego wyniku najważniejsze to SdkMessageId. W kolejnym kroku musimy zaktualizować jedną kolumnę w tabeli SdkMessageFilterBase, aby wiadomość nam się pokazała. Całe zapytanie, które to wykonuje jest następujące:

update SdkMessageFilterBase set IsCustomProcessingStepAllowed =1 where SdkMessageId = '1ABEBB1B-EA3E-DB11-86A7-000A3A5473E8'

Jak już to będziemy mieli wykonane nie pozostaje nam nic innego jak przeładować PRT i ponownie spróbować stworzyć Step, które będzie powiązany z tą wiadomością:

image

Jak wygląda kod obsługi tej wiadomości  ? Oto przykład:


public class PreSetParent : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
if (context.MessageName == "SetParent" && context.InputParameters.Properties.Contains(Attributes.UserId) && context.InputParameters.Properties.Contains(Attributes.ParentId))
{
Guid _userId = (Guid)context.InputParameters[Attributes.UserId];
Guid _parentId = (Guid)context.InputParameters[Attributes.ParentId];
}
}
}


InputParameters w IPluginExecutionContext zawiera w tym przypadku 4 właściwości. UserId oraz ParentId są odpowiednią identyfikatorem użytkownika oraz identyfikatorem Menedżera. Inne atrybuty można sobie podejrzeć debugując kod pluginu.



Rozwiązanie, które zaproponowałem jest w 100% niewspierane i korzystacie z niego na własną odpowiedzialność.