public void ShouldAddToRepositoryAndReturnTrue() { var ship = new Ship(); shipRepositoryMock.Setup(x => x.Find(shipId)).Returns(ship); var entity = new Schedule(); var result = service.Add(entity, shipId); Assert.IsTrue(result); Assert.AreEqual(ship, entity.Ship); repositoryMock.Verify(x => x.Add(entity), Times.Once()); shipRepositoryMock.Verify(x => x.Find(shipId), Times.Once()); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { Schedule schedule; ScheduleService scheduleService = new ScheduleService(); int scheduleId = int.Parse(hfScheduleId.Value); if (scheduleId == 0) { schedule = new Schedule(); scheduleService.Add(schedule, CurrentPersonId); } else { schedule = scheduleService.Get(scheduleId); } schedule.Name = tbScheduleName.Text; schedule.Description = tbScheduleDescription.Text; schedule.iCalendarContent = sbSchedule.iCalendarContent; schedule.CategoryId = cpCategory.SelectedValueAsInt(); int offsetMins = int.MinValue; if (int.TryParse(nbStartOffset.Text, out offsetMins)) { schedule.CheckInStartOffsetMinutes = offsetMins; } else { schedule.CheckInStartOffsetMinutes = null; } offsetMins = int.MinValue; if (int.TryParse(nbEndOffset.Text, out offsetMins)) { schedule.CheckInEndOffsetMinutes = offsetMins; } else { schedule.CheckInEndOffsetMinutes = null; } if (!schedule.IsValid) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction(() => { scheduleService.Save(schedule, CurrentPersonId); }); var qryParams = new Dictionary <string, string>(); qryParams["ScheduleId"] = schedule.Id.ToString(); NavigateToPage(this.CurrentPage.Guid, qryParams); }
/// <summary> /// 添加日程 /// </summary> /// <param name="context"></param> private void AddSchedule(HttpContext context) { string result = ""; string id = context.Request.Form["id"].SafeToString(); Schedule model = new Schedule(); string Name = context.Request.Form["Content"].SafeToString(); DateTime StartDate = Convert.ToDateTime(context.Request.Form["StartDate"].SafeToString()); DateTime EndDate = Convert.ToDateTime(context.Request.Form["EndDate"].SafeToString()); string AllDay = context.Request.Form["AllDay"].SafeToString(); string EndTime = context.Request.Form["EndTime"].SafeToString(); string IdCard = context.Request.Form["IdCard"].SafeToString(); model.Name = Name; model.Content = Name; model.StartDate = StartDate; model.EndDate = EndDate; model.CreateUID = IdCard; model.AllDay = Convert.ToInt32(AllDay); model.isEndTime = Convert.ToInt32(EndTime); if (id != "") { model.ID = Convert.ToInt32(id); jsonModel = bll.Update(model); } else { jsonModel = bll.Add(model); } result = "{\"result\":" + jss.Serialize(jsonModel) + "}"; context.Response.Write(result); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { Schedule schedule; var rockContext = new RockContext(); ScheduleService scheduleService = new ScheduleService(rockContext); int scheduleId = int.Parse(hfScheduleId.Value); if (scheduleId == 0) { schedule = new Schedule(); scheduleService.Add(schedule); } else { schedule = scheduleService.Get(scheduleId); } schedule.Name = tbScheduleName.Text; schedule.Description = tbScheduleDescription.Text; schedule.iCalendarContent = sbSchedule.iCalendarContent; schedule.CategoryId = cpCategory.SelectedValueAsInt(); int offsetMins = int.MinValue; if (int.TryParse(nbStartOffset.Text, out offsetMins)) { schedule.CheckInStartOffsetMinutes = offsetMins; } else { schedule.CheckInStartOffsetMinutes = null; } offsetMins = int.MinValue; if (int.TryParse(nbEndOffset.Text, out offsetMins)) { schedule.CheckInEndOffsetMinutes = offsetMins; } else { schedule.CheckInEndOffsetMinutes = null; } if (!schedule.IsValid) { // Controls will render the error messages return; } rockContext.SaveChanges(); var qryParams = new Dictionary <string, string>(); qryParams["ScheduleId"] = schedule.Id.ToString(); qryParams["ExpandedIds"] = PageParameter("ExpandedIds"); NavigateToPage(RockPage.Guid, qryParams); }
public async Task <IHttpActionResult> PostSchedule(ScheduleCreateViewModel model) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } var schedule = await _schedules.Add(new Schedule { TimeStarted = model.TimeStarted, TimeFinished = model.TimeFinished, DayOfWeek = model.DayOfWeek }); return(CreatedAtRoute("DefaultApi", new { id = schedule.Id }, (ScheduleResultViewModel)schedule)); }
protected void btnSave_Click(object sender, EventArgs e) { var rockContext = new RockContext(); RecurringCommunicationService recurringCommunicationService = new RecurringCommunicationService(rockContext); var recurringCommunication = GetRecurringCommunication(recurringCommunicationService); if (recurringCommunication.Schedule == null) { recurringCommunication.Schedule = new Schedule(); ScheduleService scheduleService = new ScheduleService(rockContext); scheduleService.Add(recurringCommunication.Schedule); } recurringCommunication.Name = tbName.Text; recurringCommunication.DataViewId = dvpDataview.SelectedValue.AsInteger(); recurringCommunication.Schedule.iCalendarContent = sbScheduleBuilder.iCalendarContent; recurringCommunication.CommunicationType = rblCommunicationType.SelectedValueAsEnum <CommunicationType>(); recurringCommunication.FromName = tbFromName.Text; recurringCommunication.FromEmail = tbFromEmail.Text; recurringCommunication.Subject = tbSubject.Text; recurringCommunication.EmailBody = ceEmailBody.Text; recurringCommunication.PhoneNumberValueId = dvpPhoneNumber.SelectedDefinedValueId > 0 ? dvpPhoneNumber.SelectedDefinedValueId : null; recurringCommunication.SMSBody = tbSMSBody.Text; recurringCommunication.PushTitle = tbPushNotificationTitle.Text; recurringCommunication.PushMessage = tbPushNotificationBody.Text; recurringCommunication.PushSound = cbPlaySound.Checked ? "default" : string.Empty; recurringCommunication.TransformationEntityTypeId = ddlTransformTypes.SelectedValue.AsIntegerOrNull(); if (recurringCommunication.Id == 0) { recurringCommunicationService.Add(recurringCommunication); } recurringCommunication.ScheduleDescription = GetScheduleDescription(); rockContext.SaveChanges(); NavigateToParentPage(); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { Metric metric; var rockContext = new RockContext(); MetricService metricService = new MetricService(rockContext); MetricCategoryService metricCategoryService = new MetricCategoryService(rockContext); MetricValueService metricValueService = new MetricValueService(rockContext); bool deleteValuesOnSave = sender == btnDeleteValuesAndSave; int metricId = hfMetricId.Value.AsInteger(); if (metricId == 0) { metric = new Metric(); } else { metric = metricService.Get(metricId); } metric.Title = tbTitle.Text; metric.Subtitle = tbSubtitle.Text; metric.Description = tbDescription.Text; metric.IconCssClass = tbIconCssClass.Text; metric.SourceValueTypeId = ddlSourceType.SelectedValueAsId(); metric.XAxisLabel = tbXAxisLabel.Text; metric.YAxisLabel = tbYAxisLabel.Text; metric.IsCumulative = cbIsCumulative.Checked; var origEntityType = metric.EntityTypeId.HasValue ? EntityTypeCache.Read(metric.EntityTypeId.Value) : null; var newEntityType = etpEntityType.SelectedEntityTypeId.HasValue ? EntityTypeCache.Read(etpEntityType.SelectedEntityTypeId.Value) : null; if (origEntityType != null && !deleteValuesOnSave) { if (newEntityType == null || newEntityType.Id != origEntityType.Id) { // if the EntityTypeId of this metric has changed to NULL or to another EntityType, warn about the EntityId values being wrong bool hasEntityValues = metricValueService.Queryable().Any(a => a.MetricId == metric.Id && a.EntityId.HasValue); if (hasEntityValues) { nbEntityTypeChanged.Text = string.Format( "Warning: You can't change the series partition to {0} when there are values associated with {1}. Do you want to delete existing values?", newEntityType != null ? newEntityType.FriendlyName : "<none>", origEntityType.FriendlyName); mdEntityTypeChanged.Show(); nbEntityTypeChanged.Visible = true; return; } } } metric.EntityTypeId = etpEntityType.SelectedEntityTypeId; int sourceTypeDataView = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_DATAVIEW.AsGuid()).Id; int sourceTypeSQL = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_SQL.AsGuid()).Id; var personService = new PersonService(rockContext); var metricChampionPerson = personService.Get(ppMetricChampionPerson.SelectedValue ?? 0); metric.MetricChampionPersonAliasId = metricChampionPerson != null ? metricChampionPerson.PrimaryAliasId : null; var adminPerson = personService.Get(ppAdminPerson.SelectedValue ?? 0); metric.AdminPersonAliasId = adminPerson != null ? adminPerson.PrimaryAliasId : null; if (metric.SourceValueTypeId == sourceTypeSQL) { metric.SourceSql = ceSourceSql.Text; } else { metric.SourceSql = string.Empty; } if (metric.SourceValueTypeId == sourceTypeDataView) { metric.DataViewId = ddlDataView.SelectedValueAsId(); } else { metric.DataViewId = null; } var scheduleSelectionType = rblScheduleSelect.SelectedValueAsEnum <ScheduleSelectionType>(); if (scheduleSelectionType == ScheduleSelectionType.NamedSchedule) { metric.ScheduleId = ddlSchedule.SelectedValueAsId(); } else { metric.ScheduleId = hfUniqueScheduleId.ValueAsInt(); } if (!Page.IsValid) { return; } if (!metric.IsValid) { // Controls will render the error messages return; } if (!cpMetricCategories.SelectedValuesAsInt().Any()) { cpMetricCategories.ShowErrorMessage("Must select at least one category"); return; } // do a WrapTransaction since we are doing multiple SaveChanges() rockContext.WrapTransaction(() => { var scheduleService = new ScheduleService(rockContext); var schedule = scheduleService.Get(metric.ScheduleId ?? 0); int metricScheduleCategoryId = new CategoryService(rockContext).Get(Rock.SystemGuid.Category.SCHEDULE_METRICS.AsGuid()).Id; if (schedule == null) { schedule = new Schedule(); // make it an "Unnamed" metrics schedule schedule.Name = string.Empty; schedule.CategoryId = metricScheduleCategoryId; } // if the schedule was a unique schedule (configured in the Metric UI, set the schedule's ical content to the schedule builder UI's value if (scheduleSelectionType == ScheduleSelectionType.Unique) { schedule.iCalendarContent = sbSchedule.iCalendarContent; } if (!schedule.HasSchedule() && scheduleSelectionType == ScheduleSelectionType.Unique) { // don't save as a unique schedule if the schedule doesn't do anything schedule = null; } else { if (schedule.Id == 0) { scheduleService.Add(schedule); // save to make sure we have a scheduleId rockContext.SaveChanges(); } } if (schedule != null) { metric.ScheduleId = schedule.Id; } else { metric.ScheduleId = null; } if (metric.Id == 0) { metricService.Add(metric); // save to make sure we have a metricId rockContext.SaveChanges(); } // update MetricCategories for Metric metric.MetricCategories = metric.MetricCategories ?? new List <MetricCategory>(); var selectedCategoryIds = cpMetricCategories.SelectedValuesAsInt(); // delete any categories that were removed foreach (var metricCategory in metric.MetricCategories.ToList()) { if (!selectedCategoryIds.Contains(metricCategory.CategoryId)) { metricCategoryService.Delete(metricCategory); } } // add any categories that were added foreach (int categoryId in selectedCategoryIds) { if (!metric.MetricCategories.Any(a => a.CategoryId == categoryId)) { metricCategoryService.Add(new MetricCategory { CategoryId = categoryId, MetricId = metric.Id }); } } rockContext.SaveChanges(); // delete MetricValues associated with the old entityType if they confirmed the EntityType change if (deleteValuesOnSave) { metricValueService.DeleteRange(metricValueService.Queryable().Where(a => a.MetricId == metric.Id && a.EntityId.HasValue)); // since there could be 1000s of values that got deleted, do a SaveChanges that skips PrePostProcessing rockContext.SaveChanges(true); } // delete any orphaned Unnamed metric schedules var metricIdSchedulesQry = metricService.Queryable().Select(a => a.ScheduleId); int?metricScheduleId = schedule != null ? schedule.Id : (int?)null; var orphanedSchedules = scheduleService.Queryable() .Where(a => a.CategoryId == metricScheduleCategoryId && a.Name == string.Empty && a.Id != (metricScheduleId ?? 0)) .Where(s => !metricIdSchedulesQry.Any(m => m == s.Id)); foreach (var item in orphanedSchedules) { scheduleService.Delete(item); } if (orphanedSchedules.Any()) { rockContext.SaveChanges(); } }); var qryParams = new Dictionary <string, string>(); qryParams["MetricId"] = metric.Id.ToString(); if (hfMetricCategoryId.ValueAsInt() == 0) { int?parentCategoryId = PageParameter("ParentCategoryId").AsIntegerOrNull(); int?metricCategoryId = new MetricCategoryService(new RockContext()).Queryable().Where(a => a.MetricId == metric.Id && a.CategoryId == parentCategoryId).Select(a => a.Id).FirstOrDefault(); hfMetricCategoryId.Value = metricCategoryId.ToString(); } qryParams["MetricCategoryId"] = hfMetricCategoryId.Value; qryParams["ExpandedIds"] = PageParameter("ExpandedIds"); NavigateToPage(RockPage.Guid, qryParams); }
public void RockCleanup_Execute_ShouldUpdateEventItemOccurrences() { var referenceDate = new DateTime(2020, 1, 1); // Get the sample data schedule for Saturday 4:30pm. var rockContext = new RockContext(); var scheduleService = new ScheduleService(rockContext); var schedule = scheduleService.Get(TestGuids.Schedules.ScheduleSat1630Guid.AsGuid()); // Create a new inactive schedule. var scheduleInactive = scheduleService.Get(testScheduleGuid); if (scheduleInactive == null) { scheduleInactive = new Schedule(); scheduleService.Add(scheduleInactive); } scheduleInactive.Name = "Test Schedule"; scheduleInactive.Guid = testScheduleGuid; scheduleInactive.IsActive = false; rockContext.SaveChanges(); // Create the Test Events. var eventItemService = new EventItemService(rockContext); // Test Event 1 (active) var testEvent1 = eventItemService.Get(testEvent1Guid); if (testEvent1 != null) { eventItemService.Delete(testEvent1); rockContext.SaveChanges(); } testEvent1 = new EventItem(); testEvent1.Guid = testEvent1Guid; testEvent1.Name = "Test Event 1"; eventItemService.Add(testEvent1); // Add an occurrence with a future schedule and no NextDateTime value. // When the cleanup task executes, this should be updated to the next occurrence after the reference date. var testOccurrence11 = new EventItemOccurrence(); testOccurrence11.ScheduleId = schedule.Id; testOccurrence11.Guid = testEventOccurrence11Guid; testOccurrence11.NextStartDateTime = null; testEvent1.EventItemOccurrences.Add(testOccurrence11); // Add an occurrence with a NextDateTime that is prior to the reference date. // When the cleanup task executes, this should be updated to the next occurrence after the reference date. var testOccurrence12 = new EventItemOccurrence(); testOccurrence12.ScheduleId = schedule.Id; testOccurrence12.Guid = testEventOccurrence12Guid; testOccurrence12.NextStartDateTime = referenceDate.AddDays(-1); testEvent1.EventItemOccurrences.Add(testOccurrence12); // Add an occurrence with a NextDateTime and an inactive Schedule. // When the cleanup task executes, the NextDateTime should be set to null. var testOccurrence13 = new EventItemOccurrence(); testOccurrence13.ScheduleId = scheduleInactive.Id; testOccurrence13.Guid = testEventOccurrence13Guid; testOccurrence13.NextStartDateTime = referenceDate.AddDays(7); testEvent1.EventItemOccurrences.Add(testOccurrence13); // Test Event 2 (inactive) var testEvent2 = eventItemService.Get(testEvent2Guid); if (testEvent2 != null) { eventItemService.Delete(testEvent2); rockContext.SaveChanges(); } testEvent2 = new EventItem(); testEvent2.Guid = testEvent2Guid; testEvent2.Name = "Test Event 2"; testEvent2.IsActive = false; eventItemService.Add(testEvent2); // Add an occurrence with a future schedule and a NextDateTime value. // When the cleanup task executes, the NextDateTime should be set to null. var testOccurrence21 = new EventItemOccurrence(); testOccurrence21.ScheduleId = schedule.Id; testOccurrence21.Guid = testEventOccurrence21Guid; testOccurrence21.NextStartDateTime = referenceDate; testEvent2.EventItemOccurrences.Add(testOccurrence21); // Save changes without triggering the pre-save, to avoid updating the NextEventDate field. rockContext.SaveChanges(new SaveChangesArgs { DisablePrePostProcessing = true }); // Run the cleanup task to verify the results for the reference date. RunRockCleanupTaskUpdateEventNextOccurrenceDatesAndVerify(referenceDate); // Re-run the task to verify that the results are adjusted for the current date. RunRockCleanupTaskUpdateEventNextOccurrenceDatesAndVerify(RockDateTime.Now); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { Metric metric; var rockContext = new RockContext(); MetricService metricService = new MetricService(rockContext); MetricCategoryService metricCategoryService = new MetricCategoryService(rockContext); int metricId = hfMetricId.Value.AsInteger(false) ?? 0; if (metricId == 0) { metric = new Metric(); } else { metric = metricService.Get(metricId); } metric.Title = tbTitle.Text; metric.Subtitle = tbSubtitle.Text; metric.Description = tbDescription.Text; metric.IconCssClass = tbIconCssClass.Text; metric.SourceValueTypeId = ddlSourceType.SelectedValueAsId(); metric.XAxisLabel = tbXAxisLabel.Text; metric.YAxisLabel = tbYAxisLabel.Text; metric.IsCumulative = cbIsCumulative.Checked; metric.EntityTypeId = etpEntityType.SelectedEntityTypeId; var personService = new PersonService(rockContext); var metricChampionPerson = personService.Get(ppMetricChampionPerson.SelectedValue ?? 0); metric.MetricChampionPersonAliasId = metricChampionPerson != null ? metricChampionPerson.PrimaryAliasId : null; var adminPerson = personService.Get(ppAdminPerson.SelectedValue ?? 0); metric.AdminPersonAliasId = adminPerson != null ? adminPerson.PrimaryAliasId : null; metric.SourceSql = ceSourceSql.Text; metric.DataViewId = ddlDataView.SelectedValueAsId(); if (rblScheduleSelect.SelectedValueAsEnum <ScheduleSelectionType>() == ScheduleSelectionType.NamedSchedule) { metric.ScheduleId = ddlSchedule.SelectedValueAsId(); } else { metric.ScheduleId = hfUniqueScheduleId.ValueAsInt(); } if (!Page.IsValid) { return; } if (!metric.IsValid) { // Controls will render the error messages return; } if (!cpMetricCategories.SelectedValuesAsInt().Any()) { cpMetricCategories.ShowErrorMessage("Must select at least one category"); return; } // do a WrapTransaction since we are doing multiple SaveChanges() RockTransactionScope.WrapTransaction(() => { var scheduleService = new ScheduleService(rockContext); var schedule = scheduleService.Get(metric.ScheduleId ?? 0); int metricScheduleCategoryId = new CategoryService(rockContext).Get(Rock.SystemGuid.Category.SCHEDULE_METRICS.AsGuid()).Id; if (schedule == null) { schedule = new Schedule(); // make it an "Unnamed" metrics schedule schedule.Name = string.Empty; schedule.CategoryId = metricScheduleCategoryId; } schedule.iCalendarContent = sbSchedule.iCalendarContent; if (schedule.Id == 0) { scheduleService.Add(schedule); // save to make sure we have a scheduleId rockContext.SaveChanges(); } metric.ScheduleId = schedule.Id; if (metric.Id == 0) { metricService.Add(metric); // save to make sure we have a metricId rockContext.SaveChanges(); } // update MetricCategories for Metric metric.MetricCategories = metric.MetricCategories ?? new List <MetricCategory>(); var selectedCategoryIds = cpMetricCategories.SelectedValuesAsInt(); // delete any categories that were removed foreach (var metricCategory in metric.MetricCategories) { if (!selectedCategoryIds.Contains(metricCategory.CategoryId)) { metricCategoryService.Delete(metricCategory); } } // add any categories that were added foreach (int categoryId in selectedCategoryIds) { if (!metric.MetricCategories.Any(a => a.CategoryId == categoryId)) { metricCategoryService.Add(new MetricCategory { CategoryId = categoryId, MetricId = metric.Id }); } } rockContext.SaveChanges(); // delete any orphaned Unnamed metric schedules var metricIdSchedulesQry = metricService.Queryable().Select(a => a.ScheduleId); var orphanedSchedules = scheduleService.Queryable() .Where(a => a.CategoryId == metricScheduleCategoryId && a.Name == string.Empty && a.Id != schedule.Id) .Where(s => !metricIdSchedulesQry.Any(m => m == s.Id)); foreach (var item in orphanedSchedules) { scheduleService.Delete(item); } if (orphanedSchedules.Any()) { rockContext.SaveChanges(); } }); var qryParams = new Dictionary <string, string>(); qryParams["MetricId"] = metric.Id.ToString(); if (hfMetricCategoryId.ValueAsInt() == 0) { int?parentCategoryId = PageParameter("ParentCategoryId").AsInteger(); int?metricCategoryId = new MetricCategoryService(new RockContext()).Queryable().Where(a => a.MetricId == metric.Id && a.CategoryId == parentCategoryId).Select(a => a.Id).FirstOrDefault(); hfMetricCategoryId.Value = metricCategoryId.ToString(); } qryParams["MetricCategoryId"] = hfMetricCategoryId.Value; NavigateToPage(RockPage.Guid, qryParams); }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public virtual void Execute(IJobExecutionContext context) { // Check Api connection first. if (!Zoom.ZoomAuthCheck()) { context.Result = "Zoom API authentication error. Check API settings for Zoom Room plugin or try again later."; throw new Exception("Authentication failed for Zoom API. Please verify the API settings configured in the Zoom Room plugin are valid and correct."); } using (var rockContext = new RockContext()) { #region Setup Variables int jobId = context.JobDetail.Description.AsInteger(); var job = new ServiceJobService(rockContext).GetNoTracking(jobId); var JobStartDateTime = RockDateTime.Now; DateTime?lastSuccessRunDateTime = null; if (job != null && job.Guid != Rock.SystemGuid.ServiceJob.JOB_PULSE.AsGuid()) { lastSuccessRunDateTime = job.LastSuccessfulRunDateTime; } // get the last run date or yesterday var beginDateTime = lastSuccessRunDateTime ?? JobStartDateTime.AddDays(-1); var dataMap = context.JobDetail.JobDataMap; var daysOut = dataMap.GetIntegerFromString(AttributeKey.SyncDaysOut); webhookBaseUrl = Settings.GetWebhookUrl(); var importMeetings = dataMap.GetBooleanFromString(AttributeKey.ImportMeetings); verboseLogging = dataMap.GetBooleanFromString(AttributeKey.VerboseLogging); var zrOccurrencesCancel = new List <RoomOccurrence>(); reservationLocationEntityTypeId = new EntityTypeService(rockContext).GetNoTracking(com.bemaservices.RoomManagement.SystemGuid.EntityType.RESERVATION_LOCATION.AsGuid()).Id; var zoom = Zoom.Api(); var locationService = new LocationService(rockContext); var zrLocations = locationService.Queryable() .AsNoTracking() .WhereAttributeValue(rockContext, a => a.Attribute.Key == "rocks.kfs.ZoomRoom" && a.Value != null && a.Value != "") .ToList(); var zrLocationIds = zrLocations.Select(l => l.Id).ToList(); var linkedZoomRoomLocations = new Dictionary <int, string>(); foreach (var loc in zrLocations) { loc.LoadAttributes(); var zoomRoomDV = DefinedValueCache.Get(loc.GetAttributeValue("rocks.kfs.ZoomRoom").AsGuid()); linkedZoomRoomLocations.Add(loc.Id, zoomRoomDV.Value); } #endregion Setup Variables #region Mark Completed Occurrences var zrOccurrenceService = new RoomOccurrenceService(rockContext); var completedOccurrences = zrOccurrenceService.Queryable() .Where(ro => ro.IsCompleted == false && DbFunctions.AddMinutes(ro.StartTime, ro.Duration) < beginDateTime); foreach (var occ in completedOccurrences) { occ.IsCompleted = true; } rockContext.SaveChanges(); #endregion Mark Completed Occurrences #region Cleanup var reservationLocationService = new ReservationLocationService(rockContext); var reservationLocationIds = reservationLocationService.Queryable().AsNoTracking().Select(rl => rl.Id); // Delete any orphaned RoomOccurrences ( tied to invalid/deleted ReservationId ) zrOccurrenceService = new RoomOccurrenceService(rockContext); var orphanedOccs = zrOccurrenceService.Queryable() .Where(ro => ro.EntityTypeId == reservationLocationEntityTypeId && !reservationLocationIds.Any(id => id == ro.EntityId)); if (orphanedOccs.Count() > 0) { if (verboseLogging) { LogEvent(rockContext, "Zoom Room Reservation Sync", string.Format("Preparing to delete {0} orphaned RoomOccurrence(s).")); } zrOccurrenceService.DeleteRange(orphanedOccs); var errors = new List <string>(); LogEvent(null, "Zoom Room Reservation Sync", string.Format("{0} orphaned RoomOccurrence(s) deleted.", orphanedOccs.Count())); if (verboseLogging) { LogEvent(null, "Zoom Room Reservation Sync", "Deleting related Zoom Meetings."); } DeleteOccurrenceZoomMeetings(orphanedOccs, zoom); rockContext.SaveChanges(); } // Delete any active Room Occurrences tied to Zoom Meetings that no longer exist. var linkedOccurrences = zrOccurrenceService .Queryable() .AsNoTracking() .Where(ro => ro.EntityTypeId == reservationLocationEntityTypeId && ro.ZoomMeetingId > 0 && !ro.IsCompleted && ro.StartTime >= beginDateTime); var zoomMeetings = new List <Meeting>(); foreach (var zrl in linkedZoomRoomLocations) { zoomMeetings.AddRange(zoom.GetZoomMeetings(zrl.Value, MeetingListType.Upcoming)); } var zoomMeetingIds = zoomMeetings.Select(m => m.Id).ToList(); var orphanedOccurrences = linkedOccurrences.Where(ro => !zoomMeetingIds.Any(mid => mid == ro.ZoomMeetingId)); if (orphanedOccurrences.Count() > 0) { zrOccurrenceService.DeleteRange(orphanedOccurrences); rockContext.SaveChanges(); } // Attempt to create Zoom Room Meeting for any Room Occurrences that may have had previous issues. var unlinkedOccurrences = zrOccurrenceService .Queryable() .Where(ro => ro.EntityTypeId == reservationLocationEntityTypeId && (!ro.ZoomMeetingId.HasValue || ro.ZoomMeetingId <= 0) && !ro.IsCompleted && ro.StartTime >= beginDateTime && (ro.ZoomMeetingRequestStatus == ZoomMeetingRequestStatus.Failed || ro.ZoomMeetingRequestStatus == ZoomMeetingRequestStatus.ZoomRoomOffline)); foreach (var rOcc in unlinkedOccurrences) { var rLoc = reservationLocationService.Queryable("Location").FirstOrDefault(rl => rl.Id == rOcc.EntityId); rLoc.Location.LoadAttributes(); rOcc.ZoomMeetingRequestStatus = ZoomMeetingRequestStatus.Requested; var zoomRoomDV = DefinedValueCache.Get(rLoc.Location.GetAttributeValue("rocks.kfs.ZoomRoom").AsGuid()); CreateOccurrenceZoomMeeting(rOcc, zoomRoomDV, zoom); } if (unlinkedOccurrences.Count() > 0) { rockContext.SaveChanges(); } #endregion Cleanup #region External Zoom Meetings var scheduleService = new ScheduleService(rockContext); var reservationService = new ReservationService(rockContext); var reservationTypeService = new ReservationTypeService(rockContext); var zoomImportReservationType = reservationTypeService.Get(RoomReservationType.ZOOMROOMIMPORT.AsGuid()); // Create RoomOccurrences for any Zoom Room meetings created outside of Rock if (importMeetings && linkedZoomRoomLocations.Count > 0) { var linkedMeetings = linkedOccurrences.Select(ro => ro.ZoomMeetingId).ToList(); var zoomRoomMeetings = zoomMeetings.Where(m => m.Start_Time > beginDateTime); var missingMeetings = zoomRoomMeetings.Where(m => !linkedMeetings.Any(mid => mid == m.Id)); if (missingMeetings.Count() > 0) { foreach (var zrl in linkedZoomRoomLocations) { foreach (var meeting in missingMeetings.Where(m => m.Host_Id == zrl.Value)) { // Build the iCal string as it is a required property on the Schedule for Room Reservation block to display the Reservation var meetingLocalTime = meeting.Start_Time.UtcDateTime.ToLocalTime(); var calendarEvent = new Event { DtStart = new CalDateTime(meetingLocalTime), DtEnd = new CalDateTime(meetingLocalTime.AddMinutes(meeting.Duration)), DtStamp = new CalDateTime(meetingLocalTime.Year, meetingLocalTime.Month, meetingLocalTime.Day) }; var calendar = new Calendar(); calendar.Events.Add(calendarEvent); var serializer = new CalendarSerializer(calendar); var schedule = new Schedule { Guid = Guid.NewGuid(), EffectiveStartDate = meetingLocalTime, EffectiveEndDate = meetingLocalTime.AddMinutes(meeting.Duration), IsActive = true, iCalendarContent = serializer.SerializeToString() }; scheduleService.Add(schedule); var location = locationService.Get(zrl.Key); var newReservation = new Reservation { Name = location.Name.Left(50), // NOTE: Reservation.Name is limited to 50 chars but Location.Name is up to 100 chars. ReservationTypeId = zoomImportReservationType.Id, Guid = Guid.NewGuid(), Schedule = schedule, NumberAttending = 0, Note = string.Format("Created from import of \"{0}\" meeting ({1}) from Zoom Room \"{2}\".", meeting.Topic, meeting.Id, zrl.Value), ApprovalState = ReservationApprovalState.Approved }; reservationService.Add(newReservation); var reservationLocation = new ReservationLocation { Reservation = newReservation, Location = location, ApprovalState = ReservationLocationApprovalState.Approved }; reservationLocationService.Add(reservationLocation); rockContext.SaveChanges(); var occurrence = new RoomOccurrence { ZoomMeetingId = meeting.Id, EntityTypeId = reservationLocationEntityTypeId, EntityId = reservationLocation.Id, Schedule = schedule, LocationId = reservationLocation.LocationId, Topic = meeting.Topic, StartTime = meetingLocalTime, Password = meeting.Password, Duration = meeting.Duration, TimeZone = meeting.Timezone }; zrOccurrenceService.Add(occurrence); rockContext.SaveChanges(); } } } } #endregion External Zoom Meetings #region Process Reservations var reservations = reservationService.Queryable("Schedule,ReservationLocations,ReservationType") .AsNoTracking() .Where(r => r.ModifiedDateTime >= beginDateTime && r.ReservationTypeId != zoomImportReservationType.Id && (r.ApprovalState == ReservationApprovalState.Approved || (!r.ReservationType.IsReservationBookedOnApproval && r.ApprovalState != ReservationApprovalState.Cancelled && r.ApprovalState != ReservationApprovalState.Denied && r.ApprovalState != ReservationApprovalState.Draft)) && r.ReservationLocations.Any(rl => zrLocationIds.Contains(rl.LocationId)) && r.Schedule != null && ((r.Schedule.EffectiveEndDate != null && r.Schedule.EffectiveEndDate > DbFunctions.AddDays(RockDateTime.Today, -1)) || (r.Schedule.EffectiveEndDate == null && r.Schedule.EffectiveStartDate != null && r.Schedule.EffectiveStartDate > DbFunctions.AddDays(RockDateTime.Today, -1)))) .ToList(); var resLocationIdsToProcess = new List <int>(); var zrOccurrencesAdded = 0; if (verboseLogging) { LogEvent(rockContext, "Zoom Room Reservation Sync", string.Format("{0} Room Reservation(s) to be processed", reservations.Count())); } foreach (var res in reservations) { foreach (var rl in res.ReservationLocations.Where(rl => zrLocationIds.Contains(rl.LocationId)).ToList()) { rl.Location.LoadAttributes(); var zoomRoomDV = DefinedValueCache.Get(rl.Location.AttributeValues.FirstOrDefault(v => v.Key == "rocks.kfs.ZoomRoom").Value.Value.AsGuid()); var zrPassword = zoomRoomDV.GetAttributeValue("rocks.kfs.ZoomMeetingPassword"); resLocationIdsToProcess.Add(rl.Id); var resLocOccurrences = zrOccurrenceService.Queryable().Where(ro => ro.EntityTypeId == reservationLocationEntityTypeId && ro.EntityId == rl.Id); // One-Time Schedule if (res.Schedule.EffectiveEndDate is null || res.Schedule.EffectiveStartDate.Value == res.Schedule.EffectiveEndDate.Value) { var occurrence = new RoomOccurrence(); if (resLocOccurrences.Count() == 0) { occurrence = new RoomOccurrence { Id = 0, EntityTypeId = reservationLocationEntityTypeId, EntityId = rl.Id, ScheduleId = res.ScheduleId, LocationId = rl.LocationId, Topic = res.Name, StartTime = res.Schedule.FirstStartDateTime.Value, Password = zrPassword, Duration = res.Schedule.DurationInMinutes, IsCompleted = false, ZoomMeetingRequestStatus = ZoomMeetingRequestStatus.Requested }; zrOccurrenceService.Add(occurrence); rockContext.SaveChanges(); zrOccurrencesAdded++; if (CreateOccurrenceZoomMeeting(occurrence, zoomRoomDV, zoom)) { rockContext.SaveChanges(); } } else { Meeting connectedMeeting = null; var updateMeeting = false; occurrence = resLocOccurrences.FirstOrDefault(); if (occurrence.ZoomMeetingId.HasValue && occurrence.ZoomMeetingId.Value > 0) { connectedMeeting = zoomMeetings.FirstOrDefault(m => m.Id == occurrence.ZoomMeetingId.Value); if (connectedMeeting == null) { occurrence.ZoomMeetingId = null; } } if (occurrence.IsCompleted) { occurrence.IsCompleted = false; } if (occurrence.ScheduleId != res.ScheduleId) { occurrence.ScheduleId = res.ScheduleId; } if (occurrence.StartTime != res.Schedule.FirstStartDateTime.Value) { occurrence.StartTime = res.Schedule.FirstStartDateTime.Value; } if (connectedMeeting != null && connectedMeeting.Start_Time != occurrence.StartTime.ToRockDateTimeOffset()) { connectedMeeting.Start_Time = occurrence.StartTime.ToRockDateTimeOffset(); updateMeeting = true; } if (occurrence.Duration != res.Schedule.DurationInMinutes) { occurrence.Duration = res.Schedule.DurationInMinutes; if (connectedMeeting != null) { connectedMeeting.Duration = res.Schedule.DurationInMinutes; updateMeeting = true; } } if (occurrence.Topic != res.Name) { occurrence.Topic = res.Name; if (connectedMeeting != null) { connectedMeeting.Topic = res.Name; updateMeeting = true; } } if (updateMeeting) { zoom.UpdateMeeting(connectedMeeting); } } }