Thursday, 29 March 2018

Deactivate Business Process Flow from Existing Records in Dynamics CRM

Overview:
In Dynamics CRM, when you deactivate the Business process flow in the system, it continues to show the Business process flow ribbon for existing records, since they are already attached to the process. This post will discuss different approaches to deactivate the process from existing records

Following are the three approaches used to deactivate/remove business process flow from existing records in Dynamics CRM
  1. Delete the business process flow
  2. Use Javascript to hide the ribbon
  3. Use SDK to remove business process flow association


Delete the business process flow
One of the easiest approach to remove the business process flow is to completely delete the Business process flow, however, doing so will permanently delete the process. It is strongly recommended to create a copy of it or take backup before deleting it

Use Javascript to hide the ribbon

Following script can be used on Form OnLoad event to hide the Business Process Flow from a particular form. However, the record will still contain reference of the business process and will continue to show the ribbon on other forms of the entity

Xrm.Page.ui.process.setVisible(false);

Use SDK to remove business process flow association

When a business process flow is created, it also creates an entity that stores the details of each instance of the process. Deleting a record in the entity removes the instance details for the corresponding record. The CRM Developer SDK can be used to create a Console Application and delete such records. Following is the code snippet that achieves this purpose

            //Create Service proxy object with CRM Organization details
            IOrganizationService _service;
            OrganizationServiceProxy proxyService;

            ClientCredentials credentials = new ClientCredentials();
            credentials.SupportInteractive = false;

            credentials.UserName.UserName = UserName;
            credentials.UserName.Password = Password;

            Uri organizationUri = new Uri(organizationUURL);
            proxyService = new OrganizationServiceProxy(organizationUri, null, credentials, null);
            _service = (IOrganizationService)proxyService;

            //Fetch records from which Business process flow needs to be dissociated in an entity using Query expression
            QueryExpression query = new QueryExpression("contact");
            query.ColumnSet = new ColumnSet(true);
            
            EntityCollection entityCollection = _service.RetrieveMultiple(query);
            
            //Loop through individual records and deactivate Business process for each of them
            foreach (Entity item in entityCollection.Entities)
            {
                try
                {                    
                    //Retrieve all active instances of the Business process, specifying the Entity name and Entity GUID
                    RetrieveProcessInstancesRequest currentProcessInstanceReq = new RetrieveProcessInstancesRequest
                    {
                        EntityId = item.Id,
                        EntityLogicalName = "contact"
                    };
                    RetrieveProcessInstancesResponse currentProcessInstanceResp = (RetrieveProcessInstancesResponse)_service.Execute(currentProcessInstanceReq);

                    //If active process instances exists, find the Process name of the respective instance and use it to delete each active instance
                    if (currentProcessInstanceReq != null && currentProcessInstanceResp.Processes != null && currentProcessInstanceResp.Processes.Entities.Count > 0)
                    {
                        //Loop through individual process instance
                        foreach (var activeProcessInstance in currentProcessInstanceResp.Processes.Entities)
                        {
                            //Confirm if Process Id Exist, if yes, get the Process details
                            if (activeProcessInstance.Attributes.Contains("processid"))
                            {
                                //Get the Process record details from the Workflow entity
                                //This entity contains details of all business process that exist in the system
                                Entity workflow = _service.Retrieve("workflow", (activeProcessInstance["processid"] as EntityReference).Id, new ColumnSet(true));

                                //Confirm if the Process name exists
                                //The Process name is the name of the Business Process Flow entity which stores instance details for each record
                                if (workflow != null && workflow.Attributes.Contains("uniquename"))
                                {                                
                                    //delete the instance details from the Business Process Flow Entity
                                    _service.Delete(workflow["uniquename"].ToString(), activeProcessInstance.Id);
                                }                                
                            }                            
                        }
                    }                    
                }
                catch (Exception ex)
                {
                    //records exception details
                }
            }




Tuesday, 27 March 2018

Update Product Images in Microsoft Dynamics AX 2012

Introduction:
Microsoft Dynamics AX 2012 contains a helper class that can be used to attach images to a product. The images can either be a location on file system or hosted somewhere on web. To upload a product's image using X++ in Dynamics Ax 2012, you can use the following code snippet

Code Snippet:
    EcoResProductImageManagement        ecoResProductImageManagement;
    RefRecId    productRecId;

    //EcoResProductImageManagement class is helper class for image management
    ecoResProductImageManagement = EcoResProductImageManagement::construct();
   
    //Assign respective Document Type Id, URL incase the image location is Web or File, if the iamge is stored in file system
    ecoResProductImageManagement.parmDocuTypeId('URL');
       
    //The image location is provided by a url path or file system path and then define the actual location of the image file
    ecoResProductImageManagement.parmIsUrlPath(true);
    ecoResProductImageManagement.parmImage("http://sampleimage.com/300442.JPG", '', EcoResProductImageUsage::External, true);
   
    //Details of the product to which image needs to be assigned
    ecoResProductImageManagement.parmRefRecId(productRecId);
    ecoResProductImageManagement.parmRefTableId(tablenum(InventTable));
    ecoResProductImageManagement.parmDataAreaId(curext()); 
   
    //execute the process, it will assign the image to the provided product
    ecoResProductImageManagement.submit();