protected override void UpdateEntity(HappeningUser entity, InvitationDto dto) { entity.Update(Enum.Parse <RSVP>(dto.Status, true), dto.ReminderXMinsBefore, dto.IsPrivate); Reminder reminder = entity.Reminder; // fetch if necessary if (reminder == null) { reminder = reminderService.GetEnt(entity.ReminderId.Value); } reminder.Update(dto.Date.AddMinutes(entity.ReminderXMinsBefore * -1), dto.Date, reminder.IsSilenced); }
public IEnumerable <IEnumerable <HappeningDto> > Get(CalendarSearchFilterDto filter) { // finding out whether the filter is asking for the logged in user or another user effects permissions User currentUser = loginService.GetCurrentUser(); // although UserId == null is a different case which doesn't need the same direct permissions check bool isCurrentUser = filter.UserId != null && filter.UserId.Value == loginService.GetCurrentUserId(true).Value; if (!isCurrentUser && filter.UserId != null) { User user = userService.GetEnt(filter.UserId.Value); // in all cases the filters will restrict private data from being shown, but an error is good feedback for a faulty case // without this, they'd just get 0 if (!user.CalendarVisibleToOthers && currentUser.Role != UserRole.Admin) { throw new HandledException(new ArgumentException("Can't view calendar for user set to private")); } } IEnumerable <HappeningDto> data = GetQueryable().Where(x => (filter.UserId == null || (x.AllUsers.Select(y => y.UserId).Contains(filter.UserId.Value) && (x.AllUsers.FirstOrDefault(y => filter.UserId.Value == y.UserId).User.CalendarVisibleToOthers || x.AllUsers.FirstOrDefault(y => filter.UserId.Value == y.UserId).User.Id == currentUser.Id || currentUser.Role == UserRole.Admin) )) && ((isCurrentUser || currentUser.Role == UserRole.Admin) || !x.IsPrivate) && ( // this complex part captures whether either the start or end time of the event is contained within the search range ( (filter.StartDate == null || x.StartTime >= filter.StartDate.Value) && (filter.EndDate == null || x.StartTime <= filter.EndDate.Value) ) || ( (filter.StartDate == null || x.EndTime >= filter.StartDate.Value) && (filter.EndDate == null || x.EndTime <= filter.EndDate.Value) ) ) ).OrderBy(x => x.StartTime) .Select(x => DtoFromEntityWithUserData(x, filter.UserId ?? currentUser.Id)); if (filter.TextualDisplay) { List <IEnumerable <HappeningDto> > result = new List <IEnumerable <HappeningDto> >(); result.Add(data); return(result); } else { // if Calendar mode, must have startDate/endDate set if (filter.StartDate == null || filter.EndDate == null || filter.StartDate.Value.Month != filter.EndDate.Value.Month) { throw new HandledException(new ArgumentException("Start and End Date filters must be set, and be within the same month, when textual display is false")); } int days = DateTime.DaysInMonth(filter.StartDate.Value.Year, filter.StartDate.Value.Month); List <HappeningDto>[] result = new List <HappeningDto> [days]; // intialize all lists for (int x = 0; x < result.Length; x++) { result[x] = new List <HappeningDto>(); } // return empty set if no data/rows if (data.Count() == 0) { return(result); } IEnumerable <HappeningDto> sortedData = data.OrderBy(x => x.StartTime); // since start and end dates can extend beyond the month the calculations can get a little complicated int currentMonth = filter.StartDate.Value.Month; int currentYear = filter.StartDate.Value.Year; DateTime earliestStart = sortedData.Select(x => x.StartTime).OrderBy(x => x).First(); DateTime latestEnd = sortedData.Select(x => x.EndTime).OrderBy(x => x).Last(); // start and end end range offset by -1 to match array notation int startDay = earliestStart.Month == currentMonth && earliestStart.Year == currentYear ? earliestStart.Day : 1; int endDay = latestEnd.Month == currentMonth && latestEnd.Year == currentYear ? latestEnd.Day : days; for (int x = startDay; x <= endDay; x++) { DateTime date = new DateTime(currentYear, currentMonth, x); Func <DateTime, DateTime> dateFlatten = (DateTime input) => new DateTime(input.Year, input.Month, input.Day); // find all happenings that are occuring on at least the particular day IEnumerable <HappeningDto> relevantRows = sortedData.Where(i => date >= dateFlatten(i.StartTime) && date <= dateFlatten(i.EndTime)); result[x - 1].AddRange(relevantRows); // days are 1 aligned, we have to -1 to convert to array positions which are 0 aligned } return(result); } }