public async Task SaveRecurringWorkItem(RecurringWorkItemDto recurringWorkItem, int userId, bool populateWorkItems = true, bool populateWorkItemAssignments = true, DateTime?overrideNow = null) { var now = overrideNow ?? _clock.UtcNow.UtcDateTime; var patrol = await _patrolRepository.GetPatrol(recurringWorkItem.PatrolId); //save the recurring work item RecurringWorkItem item = null; List <ShiftRecurringWorkItem> shifts = new List <ShiftRecurringWorkItem>(); if (recurringWorkItem.Id != default(int)) { item = await _workItemRepository.GetRecurringWorkItem(recurringWorkItem.Id); shifts = (await _workItemRepository.GetShiftRecurringWorkItems(recurringWorkItem.Id)).ToList(); } else { item = new RecurringWorkItem(); item.PatrolId = recurringWorkItem.PatrolId; item.CreatedAt = now; item.CreatedByUserId = userId; } item.AdminGroupId = recurringWorkItem.AdminGroupId; item.CompletionMode = recurringWorkItem.CompletionMode; item.DescriptionMarkup = SanitizeHtml(recurringWorkItem.DescriptionMarkup); item.Location = recurringWorkItem.Location; item.Name = recurringWorkItem.Name; if (recurringWorkItem.Shifts != null && recurringWorkItem.Shifts.Any()) { item.MaximumRandomCount = recurringWorkItem.MaximumRandomCount; item.RecurEnd = null; item.RecurIntervalCount = null; item.RecurInterval = null; item.RecurStart = null; } else { item.MaximumRandomCount = null; item.RecurEnd = recurringWorkItem.RecurEnd; item.RecurInterval = recurringWorkItem.RecurInterval; item.RecurIntervalCount = recurringWorkItem.RecurIntervalCount; item.RecurStart = recurringWorkItem.RecurStart; } if (item.Id == default(int)) { await _workItemRepository.InsertRecurringWorkItem(item); recurringWorkItem.Id = item.Id; } else { await _workItemRepository.UpdateRecurringWorkItem(item); } if (recurringWorkItem.Shifts != null && recurringWorkItem.Shifts.Any()) { await shifts.DifferenceWith(recurringWorkItem.Shifts, (wi, dto) => wi.Id == dto.Id, dto => _workItemRepository.InsertShiftRecurringWorkItem(new ShiftRecurringWorkItem() { RecurringWorkItemId = item.Id, ScheduledAtHour = dto.ScheduledAtHour, ScheduledAtMinute = dto.ScheduledAtMinute, ShiftId = dto.ShiftId, ShiftAssignmentMode = dto.ShiftAssignmentMode }), wi => _workItemRepository.DeleteShiftRecurringWorkItem(wi), (wi, dto) => { wi.ScheduledAtHour = dto.ScheduledAtHour; wi.ScheduledAtMinute = dto.ScheduledAtMinute; wi.ShiftId = dto.ShiftId; wi.ShiftAssignmentMode = dto.ShiftAssignmentMode; return(_workItemRepository.UpdateShiftRecurringWorkItem(wi)); } ); } else { foreach (var shift in shifts) { await _workItemRepository.DeleteShiftRecurringWorkItem(shift); } } if (populateWorkItems) { //save shift recurring work items if (recurringWorkItem.Shifts != null && recurringWorkItem.Shifts.Any()) { await this.PopulateShiftWorkItemOccurences(recurringWorkItem, now, userId, patrol, populateWorkItemAssignments); } else if (recurringWorkItem.RecurStart.HasValue && recurringWorkItem.RecurEnd.HasValue && recurringWorkItem.RecurInterval.HasValue && recurringWorkItem.RecurIntervalCount.HasValue) { await this.PopulateTimedWorkItemOccurences(recurringWorkItem, userId, recurringWorkItem.NextOccurenceUsers != null?recurringWorkItem.NextOccurenceUsers.Select(x => x.Id).ToList() : null, now, populateWorkItemAssignments); } else { throw new InvalidOperationException("Invalid recurrence specification"); } } }