Пример #1
0
        public void CreationThreeTimeEntriesOnEmptyDbTest()
        {
            XrmFakedContext context         = new XrmFakedContext();
            Guid            resourseId      = Guid.NewGuid();
            DateTime        startDate       = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            TimeSpan        duration        = TimeSpan.FromDays(2);
            var             targetTimeEntry = EntityFactory.CreateTimeEntry(startDate, duration, resourseId);

            PreOperationAndThenCreate(context, targetTimeEntry);

            var entities    = GetTimeEntries(new GetEntryTimeRangeRequest(startDate, startDate + duration, resourseId), context);
            var timeEntries = entities.Select(e => TimeEntryDtoConverter.ConvertToDto(e)).ToArray();

            Assert.AreEqual(3, timeEntries.Length);

            var firstNewTimeEntry = timeEntries[0];

            Assert.AreEqual(firstNewTimeEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(firstNewTimeEntry.Start, startDate.AddDays(1));
            Assert.AreEqual(firstNewTimeEntry.End, startDate.AddDays(1).EndOfTheDay());
            var secondNewTimeEntry = timeEntries[1];

            Assert.AreEqual(secondNewTimeEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(secondNewTimeEntry.Start, startDate.AddDays(2));
            Assert.AreEqual(secondNewTimeEntry.End, startDate.AddDays(2).EndOfTheDay());
            // the "target" TimeEntry is created last
            var targetEntry = timeEntries[2];

            Assert.AreEqual(targetEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(targetEntry.Start, startDate);
            Assert.AreEqual(targetEntry.End, targetEntry.Start.EndOfTheDay());
        }
Пример #2
0
        public void CreationOnlyNonExistingTimeEntriesTest()
        {
            XrmFakedContext context    = new XrmFakedContext();
            Guid            resourseId = Guid.NewGuid();
            DateTime        startDate  = new DateTime(2000, 1, 1, 9, 0, 0, DateTimeKind.Utc);
            TimeSpan        duration   = TimeSpan.FromDays(2);

            var targetTimeEntry = EntityFactory.CreateTimeEntry(startDate, duration, resourseId);

            var existingEntryStart    = startDate.AddDays(1);
            var existingEntryDuration = TimeSpan.FromHours(2);

            context.Initialize(new List <Entity> {
                EntityFactory.CreateTimeEntry(existingEntryStart, existingEntryDuration, resourseId),
            });

            var request = new GetEntryTimeRangeRequest(startDate, startDate + duration, resourseId);

            var entitiesBeforeCreation = GetTimeEntries(request, context);

            Assert.AreEqual(1, entitiesBeforeCreation.Count);
            // One TimeEnrty exists, 1 should be added before existing one and 1 should be added after existing one
            PreOperationAndThenCreate(context, targetTimeEntry);

            var entitiesAfterCreation = GetTimeEntries(request, context);
            var timeEntries           = entitiesAfterCreation.Select(e => TimeEntryDtoConverter.ConvertToDto(e)).ToArray();

            Assert.AreEqual(3, timeEntries.Length);

            var existingTimeEntry = timeEntries[0];

            Assert.AreEqual(existingTimeEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(existingTimeEntry.Start, existingEntryStart);
            Assert.AreEqual(existingTimeEntry.End, existingEntryStart + existingEntryDuration);

            var firstNewTimeEntry = timeEntries[1];

            Assert.AreEqual(firstNewTimeEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(firstNewTimeEntry.Start, startDate.Date.AddDays(2));
            Assert.AreEqual(firstNewTimeEntry.End, startDate.Date.AddDays(2).EndOfTheDay());

            // a new time entry before the existing one is a changed "target" TimeEntry
            // the "target" TimeEntry is created last
            var secondNewTimeEntry = timeEntries[2];

            Assert.AreEqual(secondNewTimeEntry.BookableResource.Id, resourseId);
            Assert.AreEqual(secondNewTimeEntry.Start, startDate);
            Assert.AreEqual(secondNewTimeEntry.End, startDate.EndOfTheDay());
        }
        public void Execute(IServiceProvider serviceProvider)
        {
            // https://docs.microsoft.com/ru-ru/powerapps/developer/data-platform/best-practices/business-logic/develop-iplugin-implementations-stateless#problematic-patterns
            // to avoid problematic pattern should create pluginExecutionFacade and pass it everywhere (instead of using a variable of class)
            var pluginExecutionFacade = new PluginExecutionFacade(serviceProvider);

            try
            {
                var context = pluginExecutionFacade.Context;
                // if another plugin creates TimeEntry then this check should be removed
                if (context.Depth > 1)
                {
                    return;
                }
                var targetEntity       = context.InputParameters.GetTargetEntity();
                var targetTimeEntryDto = TimeEntryDtoConverter.ConvertToDto(targetEntity);

                if (targetTimeEntryDto.End.Date <= targetTimeEntryDto.Start.Date)
                {
                    return;
                }
                // the main logic is located here for clarity
                var existingTimeEntrieDates = GetExistingTimeEntryDates(pluginExecutionFacade, targetTimeEntryDto);
                var date             = targetTimeEntryDto.Start.Date;
                var maxDate          = targetTimeEntryDto.End.Date;
                var datesToBeCreated = new List <DateTime>();
                while (date <= maxDate)
                {
                    if (!existingTimeEntrieDates.Contains(date))
                    {
                        datesToBeCreated.Add(date);
                    }
                    date = date.AddDays(1);
                }

                if (!datesToBeCreated.Any())
                {
                    throw new InvalidPluginExecutionException("Duplicates creation is canceled");
                }

                // target TimeEntry should be changed
                var firstDateToBeCreated = datesToBeCreated[0];
                if (targetTimeEntryDto.Start.Date == firstDateToBeCreated)
                {
                    var duration = targetTimeEntryDto.Start.EndOfTheDay() - targetTimeEntryDto.Start;
                    targetEntity.SetDuration(duration);
                    targetEntity.SetEnd(targetTimeEntryDto.Start + duration);
                }
                else
                {
                    var duration = TimeSpan.FromDays(1) - TimeSpan.FromMinutes(1);
                    targetEntity.SetStart(firstDateToBeCreated);
                    targetEntity.SetDuration(duration);
                    targetEntity.SetEnd(firstDateToBeCreated + duration);
                }
                // the first TimeEntry will be created later as the "target" TimeEntry
                datesToBeCreated.RemoveAt(0);

                foreach (var dateItem in datesToBeCreated)
                {
                    var duration  = (TimeSpan.FromDays(1) - TimeSpan.FromMinutes(1));
                    var newEntity = targetEntity.Clone();
                    newEntity.SetStart(dateItem);
                    newEntity.SetDuration(duration);
                    newEntity.SetEnd(dateItem + duration);
                    pluginExecutionFacade.OrganizationService.Create(newEntity);
                }
            }
            catch (Exception ex)
            {
                pluginExecutionFacade.TracingService.Trace("{0}: {1}", nameof(TimeEntryUniqueDatePlugin), ex.ToString());
                // just to debug
                throw new InvalidPluginExecutionException($"An error occurred in {nameof(TimeEntryUniqueDatePlugin)}.", ex);
            }
        }