예제 #1
0
        /// <summary>
        /// Creates an artifact for a given rule, ensuring the available attributes are populated on the artifact
        /// </summary>
        /// <param name="rule"></param>
        public void CreateArtifact(mcs_artifactrule rule)
        {
            var newArtifact = new mcs_artifact()
            {
                mcs_name                 = rule.mcs_name,
                mcs_ArtifactRuleId       = rule.ToEntityReference(),
                [ArtifactLookupName]     = _entityTarget.ToEntityReference(),
                mcs_ArtifactType         = rule.mcs_ArtifactType,
                mcs_CommentsInstructions = rule.mcs_CommentsInstructions,
                mcs_ReviewStatus         = new OptionSetValue(100000002) // Pending Review
            };

            // add portal Account, Contact, Incident lookups to Artifact
            if (AccountId != Guid.Empty)
            {
                newArtifact.mcs_AccountId = new EntityReference("account", AccountId);
            }
            if (ContactId != Guid.Empty)
            {
                newArtifact.mcs_Contactid = new EntityReference("contact", ContactId);
            }
            if (IncidentId != Guid.Empty)
            {
                newArtifact.mcs_CaseId = new EntityReference("incident", IncidentId);
            }

            // Set Association field based on Rule Specifier Lookup and or Specifier
            newArtifact.mcs_Association = GetArtifactAssociationByRule(rule);

            newArtifact.EntityState = EntityState.Created;
            _orgService.Create(newArtifact);
        }
        protected override void Execute(CodeActivityContext executionContext)
        {
            ITracingService             tracer         = executionContext.GetExtension <ITracingService>();
            IWorkflowContext            context        = executionContext.GetExtension <IWorkflowContext>();
            IOrganizationServiceFactory serviceFactory = executionContext.GetExtension <IOrganizationServiceFactory>();
            IOrganizationService        service        = serviceFactory.CreateOrganizationService(context.UserId);

            try
            {
                var targetId   = context.PrimaryEntityId;
                var targetName = context.PrimaryEntityName;

                var thisAnnotation = service.Retrieve(targetName, targetId, new ColumnSet(new string[] { "objectid", "createdon", "notetext" }));

                var objectRef = (EntityReference)thisAnnotation["objectid"];

                // If this annotation is for an artifact update the Artifact
                if (objectRef.LogicalName == "mcs_artifact")
                {
                    var updateArtifact = new mcs_artifact()
                    {
                        Id             = objectRef.Id,
                        mcs_Upload     = new OptionSetValue(1), // Uploaded
                        mcs_UploadDate = (DateTime)thisAnnotation["createdon"]
                    };

                    service.Update(updateArtifact);

                    // Update the Annotation if it doesn't have *WEB* in the notetext field
                    // This is required for portal visibility

                    if (!thisAnnotation.Contains("notetext"))
                    {
                        thisAnnotation["notetext"] = "*WEB*";
                        service.Update(thisAnnotation);
                    }
                    else if (((string)thisAnnotation["notetext"]).IndexOf("*WEB*") == -1)
                    {
                        thisAnnotation["notetext"] = (string)thisAnnotation["notetext"] + "*WEB*";
                        service.Update(thisAnnotation);
                    }
                }
            }
            catch (Exception e)
            {
                throw new InvalidPluginExecutionException(e.Message);
            }
        }
        protected override void Execute(CodeActivityContext executionContext)
        {
            ITracingService             tracer         = executionContext.GetExtension <ITracingService>();
            IWorkflowContext            context        = executionContext.GetExtension <IWorkflowContext>();
            IOrganizationServiceFactory serviceFactory = executionContext.GetExtension <IOrganizationServiceFactory>();
            IOrganizationService        service        = serviceFactory.CreateOrganizationService(context.UserId);

            try
            {
                tracer.Trace("ProcessingOnChange:Execute - Manage Creation/Update/Deletion of related Artifacts");

                // an exectute multiple of artifacts to update that runs after processing
                var artifactsToUpdate = new ExecuteMultipleRequest()
                {
                    Settings = new ExecuteMultipleSettings()
                    {
                        ContinueOnError = true,
                        ReturnResponses = false
                    },
                    Requests = new OrganizationRequestCollection()
                };

                Entity entityTarget = (Entity)context.InputParameters["Target"];
                var    fullEntity   = service.Retrieve(entityTarget.LogicalName, entityTarget.Id, new ColumnSet(true));

                var    incidentId         = Guid.Empty;
                var    contactId          = Guid.Empty;
                var    accountId          = Guid.Empty;
                string artifactLookupName = "";

                switch (fullEntity.LogicalName)
                {
                // Case is the Main entity for Artifact
                case Incident.EntityLogicalName:
                    artifactLookupName = "mcs_caseid";
                    incidentId         = fullEntity.Id;
                    contactId          = fullEntity.Contains("primarycontactid") ? ((EntityReference)fullEntity["primarycontactid"]).Id : Guid.Empty;
                    accountId          = fullEntity.Contains("customerid") ? ((EntityReference)fullEntity["customerid"]).Id : Guid.Empty;
                    break;

                // Related Parent
                case Account.EntityLogicalName:
                    artifactLookupName = "mcs_accountid";
                    accountId          = fullEntity.Id;
                    contactId          = fullEntity.Contains("primarycontactid") ? ((EntityReference)fullEntity["primarycontactid"]).Id : Guid.Empty;

                    using (var xrm = new CrmServiceContext(service))
                    {
                        // Find first created Child Incident to relate Artifact
                        var a = xrm.IncidentSet.Where(x => x.CustomerId.Id == fullEntity.Id)
                                .OrderBy(x => x.CreatedOn)
                                .Select(x => new Incident()
                        {
                            Id = x.Id
                        }).FirstOrDefault();

                        if (a != null)
                        {
                            incidentId = a.Id;
                        }
                    }
                    break;

                // Related Parent
                case Contact.EntityLogicalName:
                    artifactLookupName = "mcs_contactid";
                    contactId          = fullEntity.Id;
                    accountId          = fullEntity.Contains("parentcustomerid") ? ((EntityReference)fullEntity["parentcustomerid"]).Id : Guid.Empty;

                    using (var xrm = new CrmServiceContext(service))
                    {
                        // Find first created Child Incident to relate Artifact
                        var c = xrm.IncidentSet.Where(x => x.PrimaryContactId.Id == entityTarget.Id)
                                .OrderBy(x => x.CreatedOn)
                                .Select(x => new Incident()
                        {
                            Id = x.Id
                        }).FirstOrDefault();

                        if (c != null)
                        {
                            incidentId = c.Id;
                        }
                    }
                    break;

                // Related Child
                default:
                    // Retrieve WF arguments
                    artifactLookupName = ArtifactLookupSchemaName.Get(executionContext);
                    var caseLookup = CaseLookupSchemaName.Get(executionContext);

                    if (caseLookup == null || artifactLookupName == null)
                    {
                        return;
                    }

                    tracer.Trace("ProcessingOnChange:Execute - Find parent Case using lookup " + caseLookup);
                    // if we have the proper workflow arguments retrieve and set the incidentid, accountid, and contactid associated
                    // with this related record
                    incidentId = ((EntityReference)fullEntity[caseLookup]).Id;

                    using (var xrm = new CrmServiceContext(service))
                    {
                        var e = (from c in xrm.IncidentSet where c.Id == incidentId
                                 select new Incident()
                        {
                            PrimaryContactId = c.PrimaryContactId,
                            CustomerId = c.CustomerId
                        }).FirstOrDefault();

                        accountId = e.CustomerId != null ? e.CustomerId.Id : Guid.Empty;
                        contactId = e.PrimaryContactId != null ? e.PrimaryContactId.Id : Guid.Empty;
                    }
                    break;
                }

                // Find existing Artifacts related to the triggering Entity specified in the Artifact by the artifactLookupName
                tracer.Trace("ProcessingOnChange:Execute - Find Related Artifacts for " + artifactLookupName);

                List <mcs_artifact> existingArtifacts;
                using (var xrm = new CrmServiceContext(service))
                {
                    existingArtifacts = xrm.mcs_artifactSet.Where(x => ((EntityReference)x[artifactLookupName]).Id == fullEntity.Id)
                                        .Select(x => new mcs_artifact()
                    {
                        mcs_artifactid     = x.mcs_artifactid,
                        mcs_ArtifactType   = x.mcs_ArtifactType,
                        mcs_ArtifactRuleId = x.mcs_ArtifactRuleId,
                        mcs_Association    = x.mcs_Association,
                        mcs_AccountId      = x.mcs_AccountId,
                        mcs_Contactid      = x.mcs_Contactid,
                        mcs_CaseId         = x.mcs_CaseId
                    }).ToList();
                }

                tracer.Trace("ProcessingOnChange:Execute - initialize Artifact Service");
                var artifactService = new ArtifactService(service, fullEntity, artifactLookupName, accountId, contactId, incidentId);

                tracer.Trace("ProcessingOnCreation:CreateRequiredDocs Number of Artifact Rules =" + artifactService.ArtifactRules.Count());

                foreach (mcs_artifactrule r in artifactService.ArtifactRules)
                {
                    tracer.Trace("ProcessingOnCreation:CreateRequiredDocs Number of Found Rules Specifier =" + r.mcs_QuestionIdentifier + " = " + r.mcs_SuccessIndicator);
                }

                var nonApplicableArtifactRuleIds = new List <Guid>();

                // Note:  entityTarget ONLY includes the fields that have just been modified
                // For any reconciliation we would need the use the fullEntity with all Attributes
                // and we would not want to filter out null Question Identifiers for anything missed during an OnCreate.
                //
                var processingItems = from a in artifactService.ArtifactRules.Where(x => x.mcs_QuestionIdentifier != null)
                                      join b in entityTarget.Attributes on a.mcs_QuestionIdentifier equals b.Key.ToString()
                                      select new { a, b };

                tracer.Trace("ProcessingOnCreation:CreateRequiredDocs Number of ProcessingItems =" + processingItems.Count());

                foreach (var item in processingItems)
                {
                    // if we don't have a question identifer move on to the next processing item because artifact rules with no
                    // question identifier only matter in the context of a create event not update
                    if (item.b.Value == null)
                    {
                        continue;
                    }

                    var    attribute      = item.b;
                    var    artifactRule   = item.a;
                    string attributeText  = "";
                    string attributeName  = "";
                    int    attributeValue = new int();

                    attributeName = attribute.Key.ToString();
                    // we do not have artifact rules based on state or status reason, move to the next processing item
                    if (attributeName == "statuscode")
                    {
                        continue;
                    }
                    if (attributeName == "statecode")
                    {
                        continue;
                    }

                    // get the attribute text and value based on what type the attribute value is
                    switch (attribute.Value)
                    {
                    case OptionSetValue o:      // get the text value of selected item
                        attributeValue = o.Value;
                        attributeText  = ArtifactService.GetOptionSetText(entityTarget.LogicalName, attributeName, attributeValue, service);
                        break;

                    case EntityReference eRef:
                    case null: continue;

                    default:
                        attributeText = attribute.Value.ToString();
                        break;
                    }

                    // Find any existing Artifacts against this rule.
                    IEnumerable <mcs_artifact> existingArtifactsforRule = existingArtifacts.Where(x => x.mcs_ArtifactRuleId.Id == artifactRule.Id);
                    var alreadyExists = existingArtifactsforRule.Count() > 0;

                    // C# 7.0 pattern matching.. This allows us to use both string and integer values of option sets
                    switch (artifactRule.mcs_SuccessIndicator)
                    {
                    // if we can parse from the string the success indicator is an optionsetvalue
                    case string s when int.TryParse(s, out int i):
                        // if the question identifier equals the success indicator and does not already exist create the artifact
                        if (attributeValue == i)
                        {
                            if (!alreadyExists)
                            {
                                tracer.Trace("ProcessingOnChange:Execute - CreateArtifact text =" + attributeValue + "Specifier =" + i);
                                artifactService.CreateArtifact(artifactRule);
                                continue;
                            }
                        }
                        // if the question identifier does not equal the success indicator add to list of potential artifacts that need
                        // to be deleted
                        else
                        {
                            tracer.Trace("ProcessingOnChange:Execute - AddtoDeleteList text =" + attributeValue + "Specifier =" + i);
                            nonApplicableArtifactRuleIds.Add(artifactRule.Id);
                            continue;
                        }
                        break;

                    // if we have a string value in the success indicator
                    case string s:
                        // if the question identifier equals the success indicator and does not already exist create the artifact
                        if (attributeText == s)
                        {
                            if (!alreadyExists)
                            {
                                tracer.Trace("ProcessingOnChange:Execute - CreateArtifact text =" + attributeText + "  Specifier =" + s);
                                artifactService.CreateArtifact(artifactRule);
                                continue;
                            }
                        }
                        // if the question identifier does not equal the success indicator add to list of potential artifacts that need
                        // to be deleted
                        else
                        {
                            tracer.Trace("ProcessingOnChange:Execute - AddtoDeleteList text =" + attributeText + "  Specifier =" + s);
                            nonApplicableArtifactRuleIds.Add(artifactRule.Id);
                            continue;
                        }

                        break;

                    default:     // Skip to next Rule if this doesn't match
                        continue;
                    }

                    // If we didn't just create a new Artifact or add this Artifact Rule to the nonApplicable list, consider updating the Artifact if something has changed.

                    // Check if attribute is a specifier

                    if (attributeName == artifactRule.mcs_Specifier)
                    {
                        // loop through the collection of Artifacts for this rule
                        foreach (var artifact in existingArtifactsforRule)
                        {
                            // instantiate an update object for document in question
                            var updateArtifact = new mcs_artifact()
                            {
                                mcs_artifactid = artifact.Id
                            };

                            tracer.Trace("ProcessingOnChange:Execute - GetAssociationByRule ");
                            var association = artifactService.GetArtifactAssociationByRule(artifactRule);

                            tracer.Trace("ProcessingOnChange:Execute - Done ");

                            var dirty = false;

                            if (artifact.mcs_Association != association)
                            {
                                updateArtifact.mcs_Association = association;
                                dirty = true;
                            }

                            // Update Links if they don't already exist
                            if ((artifact.mcs_AccountId == null || artifact.mcs_AccountId.Id != accountId) && accountId != Guid.Empty)
                            {
                                updateArtifact.mcs_AccountId = new EntityReference("account", accountId);
                                dirty = true;
                            }
                            if ((artifact.mcs_Contactid == null || artifact.mcs_Contactid.Id != contactId) && contactId != Guid.Empty)
                            {
                                updateArtifact.mcs_Contactid = new EntityReference("contact", contactId);
                                dirty = true;
                            }

                            if ((artifact.mcs_CaseId == null || artifact.mcs_CaseId.Id != incidentId) && incidentId != Guid.Empty)
                            {
                                updateArtifact.mcs_CaseId = new EntityReference("incident", incidentId);
                                dirty = true;
                            }

                            if (dirty)
                            {
                                var updateReq = new UpdateRequest()
                                {
                                    Target = updateArtifact
                                };

                                artifactsToUpdate.Requests.Add(updateReq);
                            }
                        }
                    }

                    // Update any changed Artifacts
                    service.Execute(artifactsToUpdate);
                }
                tracer.Trace("Artifact ProcessingOnChange:Execute - Delete any related Artifacts that are no longer applicable");

                // for matches between the existing artifacts and our nonapplicable artifact rules delete the artifact
                (from a in existingArtifacts
                 join b in nonApplicableArtifactRuleIds on a.mcs_ArtifactRuleId.Id equals b
                 select a.Id).ToList().ForEach(x => service.Delete(mcs_artifact.EntityLogicalName, x));

                // throw (new Exception("testing"));
            }
            catch (SoapException e)
            {
                throw new InvalidPluginExecutionException(e.Detail.InnerXml);
            }
            catch (Exception e)
            {
                throw new InvalidPluginExecutionException(e.Message);
            }
        }