locked
Approval process for an incident RRS feed

  • Question

  • I am designing business process for incidents and wanted to know if I am going in the right direction.

    A user creates a case and completes the work.  He then resolves the case.  A workflow sends an email to the users' manager notifying that the case has been resolved.  The email contains a link to the incident.  The manager reviews the incident and then approves it by using a button that's called Approved which would assign a value to a field, which in turn triggers another workflow to let billing know that the incident has been approved.  

    I feel pretty comfortable creating the workflows to send the emails, but don't have any experience adding a "Approved" button and making it only visible to certain security roles. Is the "approved" functionality that I am looking for available as a plugin or is there a tutorial on making this work. 

    Thanks
    Friday, May 8, 2009 5:32 PM

Answers

  • Hi.

    You can use following approach:
    1. Create bit custom attribute "Approved" (for example new_approved), place it onto form. Make it readonly.
    2. Place in OnLoad Script of form incident which will be check that user have required role (for emample Security Role called "Manager") to see and edit "Approved" the field using following script:

    function UserHasRole(roleName)
    {
    	//get Current User Roles, oXml is an object
    	var oXml = GetCurrentUserRoles();
    	if(oXml != null)
    	{
    		//select the node text
    		var roles = oXml.selectNodes("//BusinessEntity/q1:name");
    		if(roles != null)
    		{
    			for( i = 0; i < roles.length; i++)
    			{
    				if(roles[i].text == roleName)
    				{
         					//return true if user has this role
    					return true;
    				}
    			}
    		}
    	}
    
    	//otherwise return false
     	return false;
    }
    
    function GetCurrentUserRoles()
    {
    	var xml = "" +
    	"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    	"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
    	GenerateAuthenticationHeader() +
    	" <soap:Body>" +
    	" <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
    	" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
    	" <q1:EntityName>role</q1:EntityName>" +
    	" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
    	" <q1:Attributes>" +
    	" <q1:Attribute>name</q1:Attribute>" +
    	" </q1:Attributes>" +
    	" </q1:ColumnSet>" +
    	" <q1:Distinct>false</q1:Distinct>" +
    	" <q1:LinkEntities>" +
    	" <q1:LinkEntity>" +
    	" <q1:LinkFromAttributeName>roleid</q1:LinkFromAttributeName>" +
    	" <q1:LinkFromEntityName>role</q1:LinkFromEntityName>" +
    	" <q1:LinkToEntityName>systemuserroles</q1:LinkToEntityName>" +
    	" <q1:LinkToAttributeName>roleid</q1:LinkToAttributeName>" +
    	" <q1:JoinOperator>Inner</q1:JoinOperator>" +
    	" <q1:LinkEntities>" +
    	" <q1:LinkEntity>" +
    	" <q1:LinkFromAttributeName>systemuserid</q1:LinkFromAttributeName>" +
    	" <q1:LinkFromEntityName>systemuserroles</q1:LinkFromEntityName>" +
    	" <q1:LinkToEntityName>systemuser</q1:LinkToEntityName>" +
    	" <q1:LinkToAttributeName>systemuserid</q1:LinkToAttributeName>" +
    	" <q1:JoinOperator>Inner</q1:JoinOperator>" +
    	" <q1:LinkCriteria>" +
    	" <q1:FilterOperator>And</q1:FilterOperator>" +
    	" <q1:Conditions>" +
    	" <q1:Condition>" +
    	" <q1:AttributeName>systemuserid</q1:AttributeName>" +
    	" <q1:Operator>EqualUserId</q1:Operator>" +
    	" </q1:Condition>" +
    	" </q1:Conditions>" +
    	" </q1:LinkCriteria>" +
    	" </q1:LinkEntity>" +
    	" </q1:LinkEntities>" +
    	" </q1:LinkEntity>" +
    	" </q1:LinkEntities>" +
    	" </query>" +
    	" </RetrieveMultiple>" +
    	" </soap:Body>" +
    	"</soap:Envelope>";
    
    	var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    
    	xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    	xmlHttpRequest.setRequestHeader("SOAPAction"," http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
    	xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    	xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
    	xmlHttpRequest.send(xml);
    
    	var resultXml = xmlHttpRequest.responseXML;
    	return(resultXml);
    }
    
    if (!UserHasRole("Manager"))//user doesn't have required role
    {
    	crmForm.all.new_approved_c.style.display = "none";//Hide control from Form
    	crmForm.all.new_approved_d.style.display = "none";
    }
    else//Have required Role
    {
    	crmForm.all.new_approved.Disabled = false;//Enable Control for editing
    }
    3. Next step you can create a workflow which will react on new_approved attribute change.

    I hope this help you to solve your issue.
    Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.com
    Friday, May 8, 2009 6:20 PM
    Moderator
  • Once you resolve a case it is closed and you can’t update it without re-activating it.
    Instead of a bit field I advise you to create a new status reason called Approved and add it to the resolved state.
    (This is done through customizations  Open the case entity  attributes  find the Status reason attribute  add Approved to resolved state)

    The next step you need take is write a plug-in on the setstate and setstatedynamicentity. The plug-in needs to check that the user’s security role matches the requested state. E.g. User can resolve with “problem solved” and Manager can resolve with “Approved”.

    My company has a Status Manager wizard that will solve your problem easily without writing code.


    Blog: http://mscrm4ever.blogspot.com/ * Website: http://gicrm.upsite.co.il/
    Friday, May 8, 2009 7:00 PM
  • Hi.

    I'm not at work now, so i will be able to give you a advice only in Tuesday... I need live CRM =)

    PS i think about English version but I don't have enough real themes for my technical blog (
    Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.com
    Friday, May 8, 2009 7:24 PM
    Moderator
  • Yes, you can reactivate the case and then close it again using the Approved state. A nice solution would be to add a grid button or menu item to the case entity, allow the manager select multiple resolved records, re-open each record on the server (webservice) and close as Approved. The manager can use the “Resolved Cases” view to filter the relevant cases. You can also create your own dialog with additional fields which can be transferred to the case resolution entity. Another feature you might consider is adding fields (that the manager wants to see) to the preview form. It seems much more convenient then opening each case separately.

     

     


    Blog: http://mscrm4ever.blogspot.com/ * Website: http://gicrm.upsite.co.il/
    Friday, May 8, 2009 8:51 PM
  • As far as I know, you cannot embed a link in a workflow email (more's the pity). The Notification accelerator may be an alternative as this gives the user an RSS feed that does link to the record (and elminates the need to a notification workflow).

    Leon Tribe
    Want to hear me talk about all things CRM? Check out my blog
    Monday, May 11, 2009 2:38 PM
  • No for this. I'm assuming the link in this case would be dynamic to the case in question. Workflow is one of those things where I often find new features so I wouldn't be surprised if it is there somewhere hidden but, to my knowledge, you can't have a workflow send an email with a url dynamically created (I'm talking in the context of the workflow tool within the client, I imagine something could be coded). You can put links in the bodies but only hard-coded links I believe.

    This is one case where I would be delighted to be wrong as you can add a location url in SharePoint at the click of a button.

    Leon Tribe
    Want to hear me talk about all things CRM? Check out my blog
    Tuesday, May 12, 2009 1:09 PM

All replies

  • Hi.

    You can use following approach:
    1. Create bit custom attribute "Approved" (for example new_approved), place it onto form. Make it readonly.
    2. Place in OnLoad Script of form incident which will be check that user have required role (for emample Security Role called "Manager") to see and edit "Approved" the field using following script:

    function UserHasRole(roleName)
    {
    	//get Current User Roles, oXml is an object
    	var oXml = GetCurrentUserRoles();
    	if(oXml != null)
    	{
    		//select the node text
    		var roles = oXml.selectNodes("//BusinessEntity/q1:name");
    		if(roles != null)
    		{
    			for( i = 0; i < roles.length; i++)
    			{
    				if(roles[i].text == roleName)
    				{
         					//return true if user has this role
    					return true;
    				}
    			}
    		}
    	}
    
    	//otherwise return false
     	return false;
    }
    
    function GetCurrentUserRoles()
    {
    	var xml = "" +
    	"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    	"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
    	GenerateAuthenticationHeader() +
    	" <soap:Body>" +
    	" <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
    	" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
    	" <q1:EntityName>role</q1:EntityName>" +
    	" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
    	" <q1:Attributes>" +
    	" <q1:Attribute>name</q1:Attribute>" +
    	" </q1:Attributes>" +
    	" </q1:ColumnSet>" +
    	" <q1:Distinct>false</q1:Distinct>" +
    	" <q1:LinkEntities>" +
    	" <q1:LinkEntity>" +
    	" <q1:LinkFromAttributeName>roleid</q1:LinkFromAttributeName>" +
    	" <q1:LinkFromEntityName>role</q1:LinkFromEntityName>" +
    	" <q1:LinkToEntityName>systemuserroles</q1:LinkToEntityName>" +
    	" <q1:LinkToAttributeName>roleid</q1:LinkToAttributeName>" +
    	" <q1:JoinOperator>Inner</q1:JoinOperator>" +
    	" <q1:LinkEntities>" +
    	" <q1:LinkEntity>" +
    	" <q1:LinkFromAttributeName>systemuserid</q1:LinkFromAttributeName>" +
    	" <q1:LinkFromEntityName>systemuserroles</q1:LinkFromEntityName>" +
    	" <q1:LinkToEntityName>systemuser</q1:LinkToEntityName>" +
    	" <q1:LinkToAttributeName>systemuserid</q1:LinkToAttributeName>" +
    	" <q1:JoinOperator>Inner</q1:JoinOperator>" +
    	" <q1:LinkCriteria>" +
    	" <q1:FilterOperator>And</q1:FilterOperator>" +
    	" <q1:Conditions>" +
    	" <q1:Condition>" +
    	" <q1:AttributeName>systemuserid</q1:AttributeName>" +
    	" <q1:Operator>EqualUserId</q1:Operator>" +
    	" </q1:Condition>" +
    	" </q1:Conditions>" +
    	" </q1:LinkCriteria>" +
    	" </q1:LinkEntity>" +
    	" </q1:LinkEntities>" +
    	" </q1:LinkEntity>" +
    	" </q1:LinkEntities>" +
    	" </query>" +
    	" </RetrieveMultiple>" +
    	" </soap:Body>" +
    	"</soap:Envelope>";
    
    	var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    
    	xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    	xmlHttpRequest.setRequestHeader("SOAPAction"," http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
    	xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    	xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
    	xmlHttpRequest.send(xml);
    
    	var resultXml = xmlHttpRequest.responseXML;
    	return(resultXml);
    }
    
    if (!UserHasRole("Manager"))//user doesn't have required role
    {
    	crmForm.all.new_approved_c.style.display = "none";//Hide control from Form
    	crmForm.all.new_approved_d.style.display = "none";
    }
    else//Have required Role
    {
    	crmForm.all.new_approved.Disabled = false;//Enable Control for editing
    }
    3. Next step you can create a workflow which will react on new_approved attribute change.

    I hope this help you to solve your issue.
    Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.com
    Friday, May 8, 2009 6:20 PM
    Moderator
  • Once you resolve a case it is closed and you can’t update it without re-activating it.
    Instead of a bit field I advise you to create a new status reason called Approved and add it to the resolved state.
    (This is done through customizations  Open the case entity  attributes  find the Status reason attribute  add Approved to resolved state)

    The next step you need take is write a plug-in on the setstate and setstatedynamicentity. The plug-in needs to check that the user’s security role matches the requested state. E.g. User can resolve with “problem solved” and Manager can resolve with “Approved”.

    My company has a Status Manager wizard that will solve your problem easily without writing code.


    Blog: http://mscrm4ever.blogspot.com/ * Website: http://gicrm.upsite.co.il/
    Friday, May 8, 2009 7:00 PM
  • Like Adi said, the case is readonly once it is Resolved.  Can it be reactivated using the code and then set the field?

    PS... Is there an english version of your blog?
    Friday, May 8, 2009 7:20 PM
  • Hi.

    I'm not at work now, so i will be able to give you a advice only in Tuesday... I need live CRM =)

    PS i think about English version but I don't have enough real themes for my technical blog (
    Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.com
    Friday, May 8, 2009 7:24 PM
    Moderator
  • Yes, you can reactivate the case and then close it again using the Approved state. A nice solution would be to add a grid button or menu item to the case entity, allow the manager select multiple resolved records, re-open each record on the server (webservice) and close as Approved. The manager can use the “Resolved Cases” view to filter the relevant cases. You can also create your own dialog with additional fields which can be transferred to the case resolution entity. Another feature you might consider is adding fields (that the manager wants to see) to the preview form. It seems much more convenient then opening each case separately.

     

     


    Blog: http://mscrm4ever.blogspot.com/ * Website: http://gicrm.upsite.co.il/
    Friday, May 8, 2009 8:51 PM
  • As far as I know, you cannot embed a link in a workflow email (more's the pity). The Notification accelerator may be an alternative as this gives the user an RSS feed that does link to the record (and elminates the need to a notification workflow).

    Leon Tribe
    Want to hear me talk about all things CRM? Check out my blog
    Monday, May 11, 2009 2:38 PM
  • I assume this post was for something else?   I send links in workflow emails all the time.
    Monday, May 11, 2009 3:15 PM
  • No for this. I'm assuming the link in this case would be dynamic to the case in question. Workflow is one of those things where I often find new features so I wouldn't be surprised if it is there somewhere hidden but, to my knowledge, you can't have a workflow send an email with a url dynamically created (I'm talking in the context of the workflow tool within the client, I imagine something could be coded). You can put links in the bodies but only hard-coded links I believe.

    This is one case where I would be delighted to be wrong as you can add a location url in SharePoint at the click of a button.

    Leon Tribe
    Want to hear me talk about all things CRM? Check out my blog
    Tuesday, May 12, 2009 1:09 PM