/// <summary> /// Returns all participations which pass the provided filters /// If no answer exists, Automatically adds appointment participations with the answer null /// </summary> private static List <AppointmentParticipation> FilterAndAppendAllParticipations(Appointment appointment, Func <AppointmentParticipation, bool> participationFilter, Func <EventParticipation, bool> eventFilter) { // First create the appointment participations for users which have no participation yet // A appointment participation is required to track the sent emails List <int> participantIds = appointment.AppointmentParticipations.Select(p => p.ParticipantId).ToList(); foreach (EventParticipation eventParticipationWithoutAppointmentParticipation in appointment.Event.EventParticipations.Where(e => !participantIds.Contains(e.ParticipantId))) { var newAppointmentParticipation = new AppointmentParticipation { Appointment = appointment, Participant = eventParticipationWithoutAppointmentParticipation.Participant, AppointmentParticipationAnswer = null, SentReminder = false, SentSummary = false }; appointment.AppointmentParticipations.Add(newAppointmentParticipation); } return(appointment.AppointmentParticipations .Where(participationFilter) .Where(p => eventFilter(p.Appointment.Event.EventParticipations.First(e => e.Participant == p.Participant))) .ToList()); }
public async Task <MyAppointmentListDto> GetMyAppointmentsAsync(int?limit, int?offset) { var treeQuery = new Domain.Logic.Sections.FlattenedTree.Query(); IEnumerable <ITree <Section> > flattenedTree = await _mediator.Send(treeQuery); Person currentPerson = await _userAccessor.GetCurrentPersonAsync(); Tuple <IQueryable <Appointment>, int> appointmentTuple = await _mediator.Send( new AppointmentList.Query(limit, offset, flattenedTree, currentPerson)); IList <MyAppointmentDto> myAppointmentDtos = await appointmentTuple.Item1 .ProjectTo <MyAppointmentDto>(_mapper.ConfigurationProvider) .ToListAsync(); foreach (MyAppointmentDto dto in myAppointmentDtos) { AppointmentParticipation participation = await _mediator.Send(new Domain.Logic.AppointmentParticipations.Details.Query( dto.Id, currentPerson.Id)); if (participation != null) { _mapper.Map(participation, dto); } } return(new MyAppointmentListDto { TotalRecordsCount = appointmentTuple.Item2, UserAppointments = myAppointmentDtos }); }
public async Task <Unit> Handle(Command request, CancellationToken cancellationToken) { Appointment existingAppointment = await _arpaContext.Appointments.FindAsync(new object[] { request.Id }, cancellationToken); AppointmentParticipation participation = existingAppointment.AppointmentParticipations .FirstOrDefault(pa => pa.PersonId == request.PersonId); if (participation == null) { participation = new AppointmentParticipation(Guid.NewGuid(), _mapper.Map <Command, Create.Command>(request)); await _arpaContext.AppointmentParticipations.AddAsync(participation, cancellationToken); } else { _mapper.Map(request, participation); _arpaContext.AppointmentParticipations.Update(participation); } if (await _arpaContext.SaveChangesAsync(cancellationToken) > 0) { return(Unit.Value); } throw new Exception("Problem updating appointment participation"); }
private static AppointmentParticipationDto CreateDto(AppointmentParticipation appointment) { return(new AppointmentParticipationDto { CreatedBy = "anonymous", CreatedAt = FakeDateTime.UtcNow, Id = appointment.Id, ModifiedAt = null, ModifiedBy = appointment.ModifiedBy, PredictionId = appointment.PredictionId, ResultId = appointment.ResultId }); }
public async Task <IActionResult> SetAppointmentResponse(SetAppointmentResponseDto setAppointmentResponseDto) { IDatabaseContext context = _getDatabaseContext(); Appointment? appointment = await context.Appointments .Include(a => a.Event) .ThenInclude(e => e.Organizer) .Include(a => a.Event) .ThenInclude(e => e.EventParticipations) .Include(a => a.AppointmentParticipations) .ThenInclude(ap => ap.Participant) .FirstOrDefaultAsync(a => a.Id == setAppointmentResponseDto.AppointmentId); if (appointment == null) { return(BadRequest(RequestStringMessages.AppointmentNotFound)); } User userToSetResponseFor = await context.Users.FindAsync(setAppointmentResponseDto.UserId); if (userToSetResponseFor == null) { return(BadRequest(RequestStringMessages.UserNotFound)); } User currentUser = await HttpContext.GetCurrentUserAsync(context); bool changingOtherUser = currentUser != userToSetResponseFor; bool userIsPartOfEvent = appointment.Event.EventParticipations.Any(e => e.ParticipantId == userToSetResponseFor.Id); if (changingOtherUser) { if (appointment.Event.Organizer != currentUser) { // Only the organizer is allowed to change another user _logger.LogInformation("{0}(): Tried to set response for user {1} for the appointment {2}, which he's not organizing", nameof(SetAppointmentResponse), userToSetResponseFor.Id, appointment.Id); return(BadRequest(RequestStringMessages.OrganizerRequired)); } if (!userIsPartOfEvent) { // A organizer shouldn't be able to add a user to the event, unless the user is participating in the event // This should prevent that a user gets added to an event he never had anything to do with return(BadRequest(RequestStringMessages.UserNotPartOfEvent)); } } // Ensure a user can't participate in a private event without an invitation if (!userIsPartOfEvent && appointment.Event.IsPrivate && (appointment.Event.Organizer != currentUser)) { return(BadRequest(RequestStringMessages.InvitationRequired)); } AppointmentParticipation appointmentParticipation = appointment.AppointmentParticipations.FirstOrDefault(e => e.ParticipantId == userToSetResponseFor.Id); if (appointmentParticipation == null) { // Create a new participation if there isn't an existing one appointmentParticipation = new AppointmentParticipation { Participant = userToSetResponseFor, Appointment = appointment }; context.AppointmentParticipations.Add(appointmentParticipation); } bool changeRelevantForSummary = (appointmentParticipation.AppointmentParticipationAnswer == AppointmentParticipationAnswer.Accepted) || (setAppointmentResponseDto.Response == AppointmentParticipationAnswer.Accepted); appointmentParticipation.AppointmentParticipationAnswer = setAppointmentResponseDto.Response; if (!appointment.Event.EventParticipations.Select(e => e.ParticipantId).Contains(currentUser.Id)) { // Automatically add a user to an event if he's not yet part of it var eventParticipation = new EventParticipation { Event = appointment.Event, Participant = currentUser }; context.EventParticipations.Add(eventParticipation); _auditLogger.LogInformation("{0}(): Joined event {1} automatically after joining appointment {2}", nameof(SetAppointmentResponse), appointment.Event.Id, appointment.Id); } await context.SaveChangesAsync(); // Handle notifications if (changingOtherUser) { _auditLogger.LogInformation("{0}(response={1}): The organizer set the response to the appointment {2} for user {3}", nameof(SetAppointmentResponse), setAppointmentResponseDto.Response, appointment.Id, userToSetResponseFor.Id); await _notificationService.NotifyOrganizerUpdatedUserInfoAsync(appointment.Event, userToSetResponseFor, "Der Organisator hat Ihre Zusage an einem Termin editiert."); } else { _logger.LogDebug("{0}(response={1}): Set own response for appointment {2}", nameof(SetAppointmentResponse), setAppointmentResponseDto.Response, appointment.Id); } if (changeRelevantForSummary) { // Don't send a last minute change if the response change is irrelevant // E.g. Changing from No Answer to Declined await _notificationService.SendLastMinuteChangeIfRequiredAsync(appointment); } else { _logger.LogDebug("{0}(response={1}): Intentionally skipped last minute change as the change wasn't relevant for the summary", nameof(SetAppointmentResponse), setAppointmentResponseDto.Response, appointment.Id); } return(Ok()); }
private static AppointmentParticipationNotificationInformation ExtractNotificationInformation(AppointmentParticipation participation) { return(new AppointmentParticipationNotificationInformation( ExtractNotificationInformation(participation.Participant), participation.AppointmentParticipationAnswer, participation.SentSummary, participation.SentReminder)); }