locked
Review Activity Notification RRS feed

  • Question

  • Dears,

    I am working with Some CR processes, As part of the process when new Change request created from template some review and Manual activities are defined in Activities Tab in the CR. The First Activity in the CR is Review Activity which do not contain any reviewer. Users should add reviewers in CR creation or later. 

    for review activity notification " Notification for Reviewers that new Review Activity assigned to them"  we used this criteria

    -Class: "Review Activity"

    -Condition: "Update"

    -Criteria: "From: Not Equal "In Progress" to Equal  "In Progress"

    -Notification: Send Notification to Reviewer 

    If Users added Reviewers during the CR creation the Workflow works as expected and notification delivered to the reviewer. 

    The Problem Comes when user create a new CR without editing the Review Activity "As they should be able to add reviewers later"

    In this case the RA status changed to In Progress with empty reviewers, if you add reviewer later the WF criteria does not match and Reviewer will not get any notification.

    I need to be able to notify Reviewers for Review Activity assignment and reassignment "Keeping in mind that in notification I should provide some information from the parent CR"

    Thanks


    Mohamed Fawzi | http://fawzi.wordpress.com

    Monday, February 25, 2013 5:48 AM

All replies

  • Hi Mohamed,

    one way to solve this would be to use relationship subscriptions (you'll have to change the XML code of your workflow similar to this blog post http://blogs.technet.com/b/servicemanager/archive/2009/12/15/custom-notification-workflow-on-incident-assignement-or-re-assignment.aspx)

    The big drawback of this approach is however, that the reviewer / implementer will get notified immediately when the relationship subscription occurs, thus also when their particular activity is not yet active. We had a same requirement and I've used Orchestrator + SCSM SDK to get this done. I'll copy and paste the blog post I've written in our intranet community. The code is currently only working for manual activities, but with a few modifications it should also run for review activities. Maybe it's helpful for you as well. This is probably not the prettiest solution to browse through the history of an object and can be error prone, therefore I higly recommend to test this fully in a test environment and only then deploy it to your PROD env. Btw. sorry for that 'basic' and maybe inefficient C# code, I don't have a strong developer Background :) 

    Here we go:

    A couple of days ago I've asked the community if it's possible to combine relationship and property subscriptions in a single notification subscription. It seems it's not possible with the current version of SCSM. This blog post provides a possible workaround for this.
     
    The requirement is still the same: We want to send an activity notification
    to the activity implementer only when the corresponding Activity becomes active
    (Status = In Progress). The workflow furthermore should ensure that when the
    activity implementer changes while the activity is already in progress, the new
    activity implementer should get notified as well. This second requirement was
    actually what made me to develop this custom workflow as it's not possible to
    monitor relationship changes and perform property validations in a single #[SCSM
    2012] subscription out of box.
    My solution is actually a Monitoring Runbook in #Orchestrator which
    contains a 'Run .Net Activity' which executes the C# code to validate if the
    last activity change was a Relationship Change.
    Let's first start with a Runbook flow overview. Here we go:

    The 2nd activity is where all the magic happens :-)
    So let's have a look on the code:

    //Initialize variable with default value
    strRunbookToBeExecuted = "False";
    
    //Create a connection to the management server
    EnterpriseManagementGroup emg = new EnterpriseManagementGroup("YOUR_SCSM_SERVER_DNS_NAME");
    
    //Get the Manual Activity class
    ManagementPackClass classMA = emg.EntityTypes.GetClass(new Guid("7ac62bd4-8fce-a150-3b40-16a39a61383d"));
    
    //Get the MA Object which triggered this Workflow
    EnterpriseManagementObject emoMA = emg.EntityObjects.GetObject<EnterpriseManagementObject>(new Guid("GUID_OF_THE_TRIGGER_ACTIVITY"), ObjectQueryOptions.Default);
                
    //Get all the history transactions for that object
    IList<EnterpriseManagementObjectHistoryTransaction> listHistory = emg.EntityObjects.GetObjectHistoryTransactions(emoMA);
    
    //Get the index of the last history transaction
    int LastIndex = listHistory.Count - 1;
    
    //Grab the last history transaction into context
    EnterpriseManagementObjectHistoryTransaction lastHistoryTransaction = listHistory[LastIndex];
    
    //Iterate through all history changes in the last history transaction
    foreach (KeyValuePair<Guid, EnterpriseManagementObjectHistory> ObjectHistory in lastHistoryTransaction.ObjectHistory)
    {
    
       //Check if last history transaction contains at least one relationship change 
       if (ObjectHistory.Value.RelationshipHistory.Count > 0)
       {
    
          //Iterate through all relationship changes if more than 1 change happened in a single history transaction
          foreach (EnterpriseManagementObjectRelationshipHistory RelationshipHistoryObj in ObjectHistory.Value.RelationshipHistory)
          {
    
             //Grab the relationship class of the current relationship change transaction
             ManagementPackRelationship mpRelationshipClass = emg.EntityTypes.GetRelationshipClass(RelationshipHistoryObj.ManagementPackRelationshipTypeId);
    
             //Check if the Relationship Class GUID is the GUID for Relationship Class 'Assigned to User' 
             if (mpRelationshipClass.Id == (new Guid("15e577a3-6bf9-6713-4eac-ba5a5b7c4722")) && RelationshipHistoryObj.ChangeType.ToString() == "Insert")
             {
    
               //If the condition above is true, set the following string variable to 'True'
               strRunbookToBeExecuted = "True";
             }
          }
       }
    
    //This branch exists because of the following reason: If an activity gets a reviewer / implementer assigned the first time, a standard SCSM workflow sets the 'First assigned date'
    //Property on the activity. Now it's possible that a workflow race condition occurs and the default workflow sets this property and writes therefore a new history transcations
    //Since this last history transaction was a property change, the branch above wouldn't be entered. The branch below checks when a property change occured, if it was of type
    //'First assigned date' and then checks the second to last history transaction if was a relationship change of type 'Assigned to User'.
    else if (ObjectHistory.Value.ClassHistory.Count > 0)
    {
     foreach (EnterpriseManagementObjectClassHistory PropertyHistoryObj in ObjectHistory.Value.ClassHistory)
      {
       foreach (KeyValuePair<ManagementPackProperty, Pair<EnterpriseManagementSimpleObject, EnterpriseManagementSimpleObject>> PropertyChange in PropertyHistoryObj.PropertyChanges)
        {
         if (PropertyChange.Key.DisplayName == "First assigned date")
          {
           LastIndex = listHistory.Count - 2;
           //Grab the second to last history transaction into context
           EnterpriseManagementObjectHistoryTransaction lastHistoryTransactionSub = listHistory[LastIndex];
    
            foreach (KeyValuePair<Guid, EnterpriseManagementObjectHistory> ObjectHistorySub in lastHistoryTransactionSub.ObjectHistory)
             {
              if (ObjectHistorySub.Value.RelationshipHistory.Count > 0)
               {
                foreach (EnterpriseManagementObjectRelationshipHistory RelationshipHistoryObjSub in ObjectHistorySub.Value.RelationshipHistory)
                 {
                  ManagementPackRelationship mpr = emg.EntityTypes.GetRelationshipClass(RelationshipHistoryObjSub.ManagementPackRelationshipTypeId);
    
                  if (mpr.Id == (new Guid("15e577a3-6bf9-6713-4eac-ba5a5b7c4722")) && RelationshipHistoryObjSub.ChangeType.ToString() == "Insert")
                   {
                    strRunbookToBeExecuted = "True after first assigned date";
                   }
                 }
               }
             }
          }
        }
      }
     }
    }

    I guess the code is very self-explanatory with the comments...
    Now it's important to publish the last used variable strRunbookToBeExecuted
    to the Orchestrator Databus in order to do validations based on its value. This
    is done in the Published Data section of the 'Run .Net Activity'.
    Furthermore it's required to define the used namespaces and the
    corresponding libraries in the Advanced section. For this script the following
    namespaces and libraries are required
     

    Namespaces:
    System
    System.Collections.Generic
    System.Linq
    System.Text
    Microsoft.EnterpriseManagement
    Microsoft.EnterpriseManagement.Common
    Microsoft.EnterpriseManagement.Configuration
     
    Assemblies:
    Microsoft.EnterpriseManagement.Core.dll (can be found in the
    subfolder \SDK Binaries in the install folder of
    SCSM)
    Microsoft.EnterpriseManagement.Packaging.dll (can be found in the
    subfolder \SDK Binaries in the install folder of
    SCSM)
    Microsoft.EnterpriseManagement.ServiceManager.dll (can be found in the
    subfolder \SDK Binaries in the install folder of SCSM)
    C:\Program
    Files\Reference
    Assemblies\Microsoft\Framework\v3.5\System.Core.dll
    C:\Program
    Files\Reference
    Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll
    C:\Program
    Files\Reference
    Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll
     
    Alright, now that we got the C# activity ready we must configure its link
    to the following activity to only proceed when the published variable equals
    True. For this, double click the Link between those two activities and configure
    in the include section the following condition:
     
     
    That's it.... The rest of the workflow is to retrieve the SMTP mail address
    of the user assigned as the activity implementer and build the email
    notification.
    If you may wonder where I'm getting the Manual Activity GUID (used in the
    C# code) from: This property is defined as an Input Parameter in the Initialize
    Data activity. For Monitoring Activities in Orchestrator we're using two-staged
    Runbook workflows. One initial Monitoring Runbook which is doing nothing than
    monitoring a particular SCSM class for updates and new objects and then passing
    the GUID to a sub-runbook by using the Invoke-Runbook Activity.
    Such a two staged runbook concept helps you to reduce the database load on
    the SCSM SMDB if you may have more than one runbook which monitors the
    same class. See also this blogpost for further details: http://blogs.technet.com/b/orchestrator/archive/2012/06/07/best-practices-which-is-better-monitoring-or-triggering.aspx
     
    So, if anyone is interested in this runbook or has any questions, drop me a
    comment and I'll get back to you asap.
    Cheers
    Alex

    Monday, February 25, 2013 9:54 AM
  • Thanks Alex for your help, I will check it in my lab

    Another way That I figured out is creating Notification Workflow on Review Activity Assignment

    <ManagementPack ContentReadable="true" SchemaVersion="1.1" OriginalSchemaVersion="1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <Manifest>
        <Identity>
          <ID>Custom.ActivityWorkflows</ID>
          <Version>7.5.2905.0</Version>
        </Identity>
        <Name>Custom Activity Workflows</Name>
        <References>
          <Reference Alias="WorkItem">
            <ID>System.WorkItem.Library</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="ActivityManagement">
            <ID>ServiceManager.ActivityManagement.Library</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="EnterpriseManagement1">
            <ID>Microsoft.EnterpriseManagement.ServiceManager.UI.Administration</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="EnterpriseManagement">
            <ID>Microsoft.EnterpriseManagement.ServiceManager.UI.Console</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="System">
            <ID>System.Library</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="CoreActivity">
            <ID>System.WorkItem.Activity.Library</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="SystemCenter">
            <ID>Microsoft.SystemCenter.Subscriptions</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="SystemCenter1">
            <ID>Microsoft.SystemCenter.Library</ID>
            <Version>7.0.8432.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
          <Reference Alias="CustomSystem_Notifications_Library">
            <ID>System.Notifications.Library</ID>
            <Version>7.5.2905.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
          </Reference>
        </References>
      </Manifest>
      <Categories>
        <Category ID="Category.Custom.ActivityWorkflows.ManagementPack" Value="EnterpriseManagement!Microsoft.EnterpriseManagement.ServiceManager.ManagementPack">
          <ManagementPackName>Custom.ActivityWorkflows</ManagementPackName>
          <ManagementPackVersion>7.5.2905.0</ManagementPackVersion>
        </Category>
        <Category ID="Category.ActivityAssignedToUserAddRule" Target="ActivityAssignedToUserAddRule" Value="EnterpriseManagement1!Microsoft.EnterpriseManagement.ServiceManager.Rules.WorkflowSubscriptions" />
        <Category ID="ServiceManager.Console.NotificationManagement.NotificationTemplates.ActivityAssignedToUserNotificationTemplate.Category" Target="ActivityAssignedToUserNotificationTemplate" Value="EnterpriseManagement1!ServiceManager.Console.NotificationManagement.NotificationTemplates.Enumeration" />
      </Categories>
      <Monitoring>
        <Rules>
          <Rule ID="ActivityAssignedToUserAddRule" Enabled="true" Target="ActivityManagement!System.WorkItem.Activity.WorkflowTarget" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
            <Category>System</Category>
            <DataSources>
              <DataSource ID="DS" TypeID="SystemCenter!Microsoft.SystemCenter.CmdbInstanceSubscription.DataSourceModule">
                <Subscription>
                  <RelationshipSubscription RelType="$MPElement[Name='CoreActivity!System.ReviewActivityHasReviewer']$" SourceType="$MPElement[Name='CoreActivity!System.WorkItem.Activity.ReviewActivity']$" TargetType="$MPElement[Name='CoreActivity!System.Reviewer']$">
                    <AddRelationship />
                  </RelationshipSubscription>
                  <PollingIntervalInSeconds>30</PollingIntervalInSeconds>
                  <BatchSize>100</BatchSize>
                </Subscription>
              </DataSource>
            </DataSources>
            <WriteActions>
              <WriteAction ID="WA" TypeID="SystemCenter!Microsoft.EnterpriseManagement.SystemCenter.Subscription.WindowsWorkflowTaskWriteAction">
                <Subscription>
                  <EnableBatchProcessing>false</EnableBatchProcessing>
                  <WindowsWorkflowConfiguration>
                    <AssemblyName>Microsoft.EnterpriseManagement.Notifications.Workflows</AssemblyName>
                    <WorkflowTypeName>Microsoft.EnterpriseManagement.Notifications.Workflows.SendNotificationsActivity</WorkflowTypeName>
                    <WorkflowParameters>
                      <WorkflowParameter Name="SubscriptionId" Type="guid">$MPElement$</WorkflowParameter>
                      <WorkflowArrayParameter Name="DataItems" Type="string">
                        <Item>$Data/.$</Item>
                      </WorkflowArrayParameter>
                      <WorkflowArrayParameter Name="InstanceIds" Type="string">
                        <Item>$Data/BaseManagedEntityId$</Item>
                      </WorkflowArrayParameter>
                      <WorkflowArrayParameter Name="TemplateIds" Type="string">
                        <Item>746fd65a-9050-4d58-507c-21d83c059aca</Item>
                      </WorkflowArrayParameter>
                      <WorkflowArrayParameter Name="PrimaryUserRelationships" Type="string">
                        <Item>$Context/Path[Relationship='CoreActivity!System.ReviewActivityHasReviewer' TypeConstraint='CoreActivity!System.Reviewer']/Path[Relationship='CoreActivity!System.ReviewerIsUser' TypeConstraint='System!System.User']$</Item>
                      </WorkflowArrayParameter>
                    </WorkflowParameters>
                    <RetryExceptions />
                    <RetryDelaySeconds>60</RetryDelaySeconds>
                    <MaximumRunningTimeSeconds>7200</MaximumRunningTimeSeconds>
                  </WindowsWorkflowConfiguration>
                </Subscription>
              </WriteAction>
            </WriteActions>
          </Rule>
        </Rules>
      </Monitoring>
      <Templates>
        <ObjectTemplate ID="ActivityAssignedToUserNotificationTemplate" TypeID="CustomSystem_Notifications_Library!System.Notification.Template.SMTP">
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template.SMTP']/Subject$">&lt;1033&gt;Activity $Context/Property[Type='WorkItem!System.WorkItem']/Id$ is assigned to you&lt;/1033&gt;</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template.SMTP']/Priority$">2</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template.SMTP']/IsBodyHtml$">False</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template']/Content$">&lt;1033&gt;Details:
     
    Title: $Context/Property[Type='WorkItem!System.WorkItem']/Title$
    Description: $Context/Property[Type='WorkItem!System.WorkItem']/Description$
    Created By: $Context/Path[Relationship='WorkItem!System.WorkItemCreatedByUser' TypeConstraint='System!System.User']$?$DisplayName$?
    &lt;/1033&gt;</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template']/Encoding$">utf-8</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template']/SeedClass$">System.WorkItem.Activity$3fc62adf-d590-ed19-587e-e029aecb738d</Property>
          <Property Path="$Context/Property[Type='CustomSystem_Notifications_Library!System.Notification.Template']/Protocol$">SMTP</Property>
        </ObjectTemplate>
      </Templates>
      <LanguagePacks>
        <LanguagePack ID="ENU" IsDefault="true">
          <DisplayStrings>
            <DisplayString ElementID="Custom.ActivityWorkflows">
              <Name>Custom Activity Workflows</Name>
            </DisplayString>
            <DisplayString ElementID="ActivityAssignedToUserAddRule">
              <Name>Assigned to user added to activity</Name>
            </DisplayString>
            <DisplayString ElementID="ActivityAssignedToUserNotificationTemplate">
              <Name>Activity assigned to user template</Name>
            </DisplayString>
          </DisplayStrings>
        </LanguagePack>
      </LanguagePacks>
    </ManagementPack>


    Mohamed Fawzi | http://fawzi.wordpress.com

    Monday, February 25, 2013 4:04 PM
  • Hi Alex,

    also I am interested in the Runbook, Can you Please send to me ?

    Regards,


    Mohamed Fawzi | http://fawzi.wordpress.com

    Wednesday, February 27, 2013 5:41 PM
  • How can I contact you?

    Friday, March 1, 2013 7:39 AM
  • mohamed.emam@Linkdev.com

    Mohamed Fawzi | http://fawzi.wordpress.com

    Friday, March 1, 2013 12:02 PM
  • Hi Alexander,

    I tested your MA RB and it work beautifully. The only thing lacking is that it doesnt get triggered when the activity becomes In Progress. 

    Can you also help me implement the RA version in the C# code?

    Regards.


    • Edited by Ozge Ozkaya Friday, December 15, 2017 5:54 PM
    Wednesday, December 13, 2017 6:41 PM