Skip to content

Commit

Permalink
Merge pull request #147 from SaintAngeLs/events_service
Browse files Browse the repository at this point in the history
Events service update - new GetStudentEvents functionality
  • Loading branch information
eggwhat authored May 15, 2024
2 parents 449102a + 2aa43be commit 166516f
Show file tree
Hide file tree
Showing 16 changed files with 196 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ public static async Task Main(string[] args)
.Post<ShowInterestInEvent>("events/{eventId}/show-interest")
.Delete<CancelInterestInEvent>("events/{eventId}/show-interest")
.Post<RateEvent>("events/{eventId}/rate")
.Delete<CancelRateEvent>("events/{eventId}/rate")
.Get<GetStudentEvents, PagedResponse<IEnumerable<EventDto>>>("events/student/{studentId}")
.Get<GetEventParticipants, EventParticipantsDto>("events/{eventId}/participants")
.Get<GetEventRating, EventRatingDto>("events/{eventId}/rating")
.Post<AddEventParticipant>("events/{eventId}/participants")
.Delete<RemoveEventParticipant>("events/{eventId}/participants")
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using Convey.CQRS.Commands;

namespace MiniSpace.Services.Events.Application.Commands
{
public class CancelRateEvent: ICommand
{
public Guid EventId { get; set; }
public Guid StudentId { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Threading;
using System.Threading.Tasks;
using Convey.CQRS.Commands;
using MiniSpace.Services.Events.Application.Exceptions;
using MiniSpace.Services.Events.Core.Repositories;

namespace MiniSpace.Services.Events.Application.Commands.Handlers
{
public class CancelRateEventHandler : ICommandHandler<CancelRateEvent>
{
private readonly IEventRepository _eventRepository;

public CancelRateEventHandler(IEventRepository eventRepository)
{
_eventRepository = eventRepository;
}

public async Task HandleAsync(CancelRateEvent command, CancellationToken cancellationToken)
{
var @event = await _eventRepository.GetAsync(command.EventId);
if (@event is null)
{
throw new EventNotFoundException(command.EventId);
}

@event.CancelRate(command.StudentId);
await _eventRepository.UpdateAsync(@event);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class EventDto
public DateTime UpdatedAt { get; set; }
public bool IsSignedUp { get; set; }
public bool IsInterested { get; set; }
public bool HasRated { get; set; }
public int? StudentRating { get; set; }
public IEnumerable<ParticipantDto> FriendsInterestedIn { get; set; }
public IEnumerable<ParticipantDto> FriendsSignedUp { get; set; }

Expand All @@ -52,7 +52,7 @@ public EventDto(Event @event, Guid studentId)
PublishDate = @event.PublishDate;
IsSignedUp = @event.SignedUpStudents.Any(x => x.StudentId == studentId);
IsInterested = @event.InterestedStudents.Any(x => x.StudentId == studentId);
HasRated = @event.Ratings.Any(x => x.StudentId == studentId);
StudentRating = @event.Ratings.FirstOrDefault(x => x.StudentId == studentId)?.Value;
FriendsInterestedIn = Enumerable.Empty<ParticipantDto>();
FriendsSignedUp = Enumerable.Empty<ParticipantDto>();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace MiniSpace.Services.Events.Application.DTO
{
public class EventRatingDto
{
public Guid EventId { get; set; }
public int TotalRatings { get; set; }
public double AverageRating { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using Convey.CQRS.Queries;
using MiniSpace.Services.Events.Application.DTO;

namespace MiniSpace.Services.Events.Application.Queries
{
public class GetEventRating : IQuery<EventRatingDto>
{
public Guid EventId { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace MiniSpace.Services.Events.Application.Queries
public class GetStudentEvents : IQuery<PagedResponse<IEnumerable<EventDto>>>
{
public Guid StudentId { get; set; }
public string EngagementType { get; set; }
public int Page { get; set; }
public int NumberOfResults { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,18 @@ public void Rate(Guid studentId, int rating)
throw new InvalidRatingValueException(rating);
}

if (_ratings.Any(r => r.StudentId == studentId))
_ratings.Add(new Rating(studentId, rating));
}

public void CancelRate(Guid studentId)
{
var rating = _ratings.SingleOrDefault(r => r.StudentId == studentId);
if (rating is null)
{
throw new StudentAlreadyRatedEventException(Id, studentId);
throw new StudentNotRatedEventException(studentId, Id);
}

_ratings.Add(new Rating(studentId, rating));
_ratings.Remove(rating);
}

public bool UpdateState(DateTime now)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace MiniSpace.Services.Events.Core.Exceptions
{
public class StudentNotRatedEventException : DomainException
{
public override string Code { get; } = "student_not_rated_event";
public Guid EventId { get; }
public Guid StudentId { get; }

public StudentNotRatedEventException(Guid eventId, Guid studentId)
: base($"Student with ID: '{studentId}' has not rated event with ID: '{eventId}'.")
{
EventId = eventId;
StudentId = studentId;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ public interface IEventRepository
Task<(IEnumerable<Event> events, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseEventsAsync(
int pageNumber, int pageSize, string name, string organizer, DateTime dateFrom, DateTime dateTo,
Category? category, State? state, IEnumerable<Guid> friends, EventEngagementType? friendsEngagementType,
IEnumerable<string> sortBy, string direction, IEnumerable<Guid> eventIds = null);
IEnumerable<string> sortBy, string direction);
Task<(IEnumerable<Event> events, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseOrganizerEventsAsync(
int pageNumber, int pageSize, string name, Guid organizerId, DateTime dateFrom, DateTime dateTo,
IEnumerable<string> sortBy, string direction, State? state);
Task<(IEnumerable<Event> events, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseStudentEventsAsync(
int pageNumber, int pageSize, IEnumerable<Guid> eventIds, IEnumerable<string> sortBy, string direction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static EventDto AsDto(this EventDocument document, Guid studentId)
UpdatedAt = document.UpdatedAt,
IsSignedUp = document.SignedUpStudents.Any(x => x.StudentId == studentId),
IsInterested = document.InterestedStudents.Any(x => x.StudentId == studentId),
HasRated = document.Ratings.Any(x => x.StudentId == studentId)
StudentRating = document.Ratings.FirstOrDefault(x => x.StudentId == studentId)?.Value,
};

public static EventDto AsDtoWithFriends(this EventDocument document, Guid studentId, IEnumerable<FriendDto> friends)
Expand Down Expand Up @@ -76,6 +76,14 @@ public static EventParticipantsDto AsDto(this EventDocument document)
InterestedStudents = document.InterestedStudents.Select(p => p.AsDto()),
SignedUpStudents = document.SignedUpStudents.Select(p => p.AsDto())
};

public static EventRatingDto AsRatingDto(this EventDocument document)
=> new ()
{
EventId = document.Id,
TotalRatings = document.Ratings.Count(),
AverageRating = document.Ratings.Any() ? document.Ratings.Average(x => x.Value) : 0
};

public static AddressDto AsDto(this Address entity)
=> new ()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Convey.CQRS.Queries;
using Convey.Persistence.MongoDB;
using MiniSpace.Services.Events.Application;
using MiniSpace.Services.Events.Application.DTO;
using MiniSpace.Services.Events.Application.Queries;
using MiniSpace.Services.Events.Infrastructure.Mongo.Documents;

namespace MiniSpace.Services.Events.Infrastructure.Mongo.Queries.Handlers
{
public class GetEventRatingHandler : IQueryHandler<GetEventRating, EventRatingDto>
{
private readonly IMongoRepository<EventDocument, Guid> _eventRepository;
private readonly IAppContext _appContext;

public GetEventRatingHandler(IMongoRepository<EventDocument, Guid> eventRepository,
IAppContext appContext)
{
_eventRepository = eventRepository;
_appContext = appContext;
}

public async Task<EventRatingDto> HandleAsync(GetEventRating query, CancellationToken cancellationToken)
{
var document = await _eventRepository.GetAsync(p => p.Id == query.EventId);
if(document is null)
{
return null;
}
var identity = _appContext.Identity;
if(identity.IsAuthenticated && identity.Id != document.Organizer.Id && !identity.IsAdmin)
{
return null;
}

return document.AsRatingDto();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ public class GetStudentEventsHandler : IQueryHandler<GetStudentEvents, PagedResp
{
private readonly IEventRepository _eventRepository;
private readonly IStudentsServiceClient _studentsServiceClient;
private readonly IEventValidator _eventValidator;
private readonly IAppContext _appContext;

public GetStudentEventsHandler(IEventRepository eventRepository,
IStudentsServiceClient studentsServiceClient, IAppContext appContext)
IStudentsServiceClient studentsServiceClient, IEventValidator eventValidator, IAppContext appContext)
{
_eventRepository = eventRepository;
_studentsServiceClient = studentsServiceClient;
_eventValidator = eventValidator;
_appContext = appContext;
}

Expand All @@ -40,15 +42,21 @@ public async Task<PagedResponse<IEnumerable<EventDto>>> HandleAsync(GetStudentEv
1, query.NumberOfResults, 0, 0);
}

var engagementType = _eventValidator.ParseEngagementType(query.EngagementType);

var studentEvents = await _studentsServiceClient.GetAsync(query.StudentId);
var studentEventIds = studentEvents.InterestedInEvents.Union(studentEvents.SignedUpEvents).ToList();
var studentEventIds = engagementType switch
{
EventEngagementType.SignedUp => studentEvents.SignedUpEvents.ToList(),
EventEngagementType.InterestedIn => studentEvents.InterestedInEvents.ToList(),
_ => []
};

var result = await _eventRepository.BrowseEventsAsync(1, query.NumberOfResults,
string.Empty, string.Empty, DateTime.MinValue, DateTime.MinValue, null, null,
Enumerable.Empty<Guid>(), null, Enumerable.Empty<string>(), "asc", studentEventIds);
var result = await _eventRepository.BrowseStudentEventsAsync(query.Page,
query.NumberOfResults, studentEventIds, Enumerable.Empty<string>(), "asc");

return new PagedResponse<IEnumerable<EventDto>>(result.Item1.Select(e => new EventDto(e, identity.Id)),
result.Item2, result.Item3, result.Item4, result.Item5);;
return new PagedResponse<IEnumerable<EventDto>>(result.events.Select(e => new EventDto(e, identity.Id)),
result.pageNumber, result.pageSize, result.totalPages, result.totalElements);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -53,9 +54,9 @@ public async Task<IEnumerable<Event>> GetAllAsync()
public async Task<(IEnumerable<Event> events, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseEventsAsync(
int pageNumber, int pageSize, string name, string organizer, DateTime dateFrom, DateTime dateTo,
Category? category, State? state, IEnumerable<Guid> friends, EventEngagementType? friendsEngagementType,
IEnumerable<string> sortBy, string direction, IEnumerable<Guid> eventIds = null)
IEnumerable<string> sortBy, string direction)
{
var filterDefinition = Extensions.ToFilterDefinition(name, dateFrom, dateTo, eventIds)
var filterDefinition = Extensions.ToFilterDefinition(name, dateFrom, dateTo)
.AddOrganizerNameFilter(organizer)
.AddCategoryFilter(category)
.AddRestrictedStateFilter(state)
Expand Down Expand Up @@ -83,6 +84,20 @@ public async Task<IEnumerable<Event>> GetAllAsync()
pagedEvents.totalPages, pagedEvents.totalElements);
}

public async Task<(IEnumerable<Event> events, int pageNumber, int pageSize, int totalPages, int totalElements)> BrowseStudentEventsAsync(
int pageNumber, int pageSize, IEnumerable<Guid> eventIds, IEnumerable<string> sortBy, string direction)
{
var filterDefinition = Extensions.CreateFilterDefinition()
.AddEventIdFilter(eventIds);

var sortDefinition = Extensions.ToSortDefinition(sortBy, direction);

var pagedEvents = await BrowseAsync(filterDefinition, sortDefinition, pageNumber, pageSize);

return (pagedEvents.data.Select(e => e.AsEntity()), pageNumber, pageSize,
pagedEvents.totalPages, pagedEvents.totalElements);
}

public Task AddAsync(Event @event) => _repository.AddAsync(@event.AsDocument());
public Task UpdateAsync(Event @event) => _repository.UpdateAsync(@event.AsDocument());
public Task DeleteAsync(Guid id) => _repository.DeleteAsync(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,15 @@ public static class Extensions

return (totalPages, (int)count, data);
}

public static FilterDefinition<EventDocument> CreateFilterDefinition()
{
return FilterDefinitionBuilder.Empty;
}

public static FilterDefinition<EventDocument> ToFilterDefinition(string name, DateTime dateFrom,
DateTime dateTo, IEnumerable<Guid> eventIds = null)
public static FilterDefinition<EventDocument> ToFilterDefinition(string name, DateTime dateFrom, DateTime dateTo)
{
var filterDefinition = FilterDefinitionBuilder.Empty;
var filterDefinition = CreateFilterDefinition();

if (!string.IsNullOrWhiteSpace(name))
{
Expand All @@ -80,11 +84,6 @@ public static FilterDefinition<EventDocument> ToFilterDefinition(string name, Da
filterDefinition &= FilterDefinitionBuilder.Lte(x => x.EndDate, dateTo);
}

if (eventIds != null)
{
filterDefinition &= FilterDefinitionBuilder.In(x => x.Id, eventIds);
}

return filterDefinition;
}

Expand Down Expand Up @@ -165,6 +164,13 @@ public static FilterDefinition<EventDocument> AddFriendsFilter (this FilterDefin
return filterDefinition;
}

public static FilterDefinition<EventDocument> AddEventIdFilter(this FilterDefinition<EventDocument> filterDefinition,
IEnumerable<Guid> eventIds)
{
filterDefinition &= FilterDefinitionBuilder.In(x => x.Id, eventIds);
return filterDefinition;
}

public static SortDefinition<EventDocument> ToSortDefinition(IEnumerable<string> sortByArguments, string direction)
{
var sort = sortByArguments.ToList();
Expand Down

0 comments on commit 166516f

Please sign in to comment.