delegateas / XrmMockup

Engine which simulates your exact Dynamics 365/CRM instance locally including all of it's logic!
Other
71 stars 29 forks source link

XrmMockup does not act as Dataverse when an Incident is Resolved by an IncidentResolution #208

Closed jacobblom closed 2 months ago

jacobblom commented 2 years ago

Consider a plugin that triggers on Post-Update for Incidents, filters on State-changes and looks for the state-change that resolves the incident. This event is caused by the creation of a IncidentResolution that resolves the Incident.

In Dataverse you can retrieve and delete the IncidentResolution that caused the state change of the Incident from such a plugin.

With XrmMockup you cannot retrieve the IncidentResolution from the plugin as it does not appear to exist until the plugin-pipeline for the incident has completed.

Sample plugin:

public class IncidentDeleteAllRelatedResolutionsOnClose : Plugin
    {
        public IncidentDeleteAllRelatedResolutionsOnClose() : base(typeof(IncidentDeleteAllRelatedResolutionsOnClose))
        {
            RegisterPluginStep<Incident>(
                EventOperation.Update,
                ExecutionStage.PostOperation,
                ExecuteDeleteAllRelatedResolutionsOnClose)
                .AddFilteredAttributes(x => x.StateCode)
                .AddImage(ImageType.PreImage, x => x.StateCode)
                .AddImage(ImageType.PostImage, x => x.StateCode)
                .SetExecutionOrder(10); 
        }

        protected void ExecuteDeleteAllRelatedResolutionsOnClose(LocalPluginContext localContext)
        {
            if (new ManagerUtility(localContext).IsDataMoverAction()) return; 
            new ManagerIncident(localContext).DeleteAllRelatedResolutionsOnClose(localContext.GetPreImage<Incident>(), localContext.GetPostImage<Incident>());
        }
    }

Method in Manager:

public void DeleteAllRelatedResolutionsOnClose(Incident preImage, Incident postImage)
        {
            if (preImage.StateCode == IncidentState.Active && postImage.StateCode != IncidentState.Active)
            {
                var relatedResolutionIds = _admindao.RetrieveList<Guid>(xrm => xrm.IncidentResolutionSet.Where(x => x.IncidentId.Id == _pluginContext.PrimaryEntityId).Select(x => x.Id));
                relatedResolutionIds.ForEach(x => _admindao.Delete<IncidentResolution>(x));
            }
        }

Sample unit test that fails for XrmMockup:

public void TestRemovalOfResolutionsAfterClose()
        {
            // arrange
            var id = _godDao.Create(new Incident() { });

            // act
            var incidentResolution = new IncidentResolution
            {
                Subject = "Resolved Sample Incident",
                IncidentId = id.ToEntityReference<Incident>()
            };
            var closeIncidentRequest = new CloseIncidentRequest
            {
                IncidentResolution = incidentResolution,
                Status = new OptionSetValue((int)Incident_StatusCode.Afgreitt)
            };
            _adminDao.Execute(closeIncidentRequest);

            // assert
            var retrievedIncidentResultionIds = _godDao.RetrieveList<Guid>(xrm => xrm.IncidentResolutionSet.Where(x => x.IncidentId.Id == id).Select(x => x.Id));
            Assert.Empty(retrievedIncidentResultionIds);
        }

Comments to the code: Besides the use of Daxif# and XrmFramework which are familar to most XrmMockup-users there is a concept of a "dao" in the above. Consider it a way of wrapping the use of the organisation service and getting rid of a lot of "plumbing"-code. It is not important in order to understand what is going on in the plugin.