diff --git a/Retroactiune.Core/Interfaces/IFeedbacksService.cs b/Retroactiune.Core/Interfaces/IFeedbacksService.cs index fc124d1..e1c1231 100644 --- a/Retroactiune.Core/Interfaces/IFeedbacksService.cs +++ b/Retroactiune.Core/Interfaces/IFeedbacksService.cs @@ -1,5 +1,7 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Retroactiune.Core.Entities; +using Retroactiune.Core.Services; namespace Retroactiune.Core.Interfaces { @@ -13,5 +15,12 @@ namespace Retroactiune.Core.Interfaces /// The feedback receiver. /// public Task AddFeedbackAsync(Feedback feedback, FeedbackReceiver receiver); + + /// + /// Gets Feedbacks. + /// + /// Filters for filtering the response. + /// An enumerable of feedbacks. + Task> GetFeedbacksAsync(FeedbacksListFilters filters); } } \ No newline at end of file diff --git a/Retroactiune.Core/Services/FeedbacksListFilters.cs b/Retroactiune.Core/Services/FeedbacksListFilters.cs new file mode 100644 index 0000000..a0c4cde --- /dev/null +++ b/Retroactiune.Core/Services/FeedbacksListFilters.cs @@ -0,0 +1,31 @@ +using System; + +namespace Retroactiune.Core.Services +{ + /// + /// FeedbacksListFilters is a data class for filtering Feedbacks. + /// + public class FeedbacksListFilters + { + + /// + /// FeedbackReceiverId the ID of the FeedbackReceiver. + /// + public string FeedbackReceiverId { get; set; } + + /// + /// CreatedAfter filters items that have been created after the given date. + /// + public DateTime? CreatedAfter { get; set; } + + /// + /// CreatedBefore filters items that have been created before the given date. + /// + public DateTime? CreatedBefore { get; set; } + + /// + /// Rating filters for the rating. + /// + public uint Rating { get; set; } + } +} \ No newline at end of file diff --git a/Retroactiune.Core/Services/FeedbacksService.cs b/Retroactiune.Core/Services/FeedbacksService.cs index ab20416..4c6630f 100644 --- a/Retroactiune.Core/Services/FeedbacksService.cs +++ b/Retroactiune.Core/Services/FeedbacksService.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Ardalis.GuardClauses; using MongoDB.Driver; using Retroactiune.Core.Entities; @@ -13,9 +14,9 @@ namespace Retroactiune.Core.Services public FeedbacksService(IMongoClient client, IDatabaseSettings settings) { var database = client.GetDatabase(settings.DatabaseName); - _collection = database.GetCollection(settings.FeedbacksCollectionName); + _collection = database.GetCollection(settings.FeedbacksCollectionName); } - + public async Task AddFeedbackAsync(Feedback feedback, FeedbackReceiver receiver) { Guard.Against.Null(feedback, nameof(feedback)); @@ -24,5 +25,34 @@ namespace Retroactiune.Core.Services feedback.FeedbackReceiverId = receiver.Id; await _collection.InsertOneAsync(feedback); } + + public async Task> GetFeedbacksAsync(FeedbacksListFilters filters) + { + // TODO: Unit test. + Guard.Against.Null(filters, nameof(filters)); + Guard.Against.Null(filters.FeedbackReceiverId, nameof(filters.FeedbackReceiverId)); + + var filterBuilder = new FilterDefinitionBuilder(); + var activeFilters = new List> + { + // Filter tokens by their assigned feedback receiver id. + filterBuilder.Eq(i => i.FeedbackReceiverId, filters.FeedbackReceiverId) + }; + + // Datetime after + if (filters.CreatedAfter != null) + { + activeFilters.Add(filterBuilder.Gte(i => i.CreatedAt, filters.CreatedAfter)); + } + + // Datetime before + if (filters.CreatedBefore != null) + { + activeFilters.Add(filterBuilder.Lte(i => i.CreatedAt, filters.CreatedBefore)); + } + + var results = await _collection.FindAsync(filterBuilder.And(activeFilters)); + return await results.ToListAsync(); + } } } \ No newline at end of file diff --git a/Retroactiune.Core/Services/TokenListFilters.cs b/Retroactiune.Core/Services/TokenListFilters.cs index 1c46eb9..7b1f733 100644 --- a/Retroactiune.Core/Services/TokenListFilters.cs +++ b/Retroactiune.Core/Services/TokenListFilters.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Retroactiune.Core.Services { /// - /// TokenListFilters is a data class representing the filters used to list tokens. + /// TokenListFilters is a data class for filtering Tokens. /// public class TokenListFilters { diff --git a/Retroactiune.WebAPI/Controllers/FeedbackReceiversController.cs b/Retroactiune.WebAPI/Controllers/FeedbackReceiversController.cs index 75e22a6..4f694fe 100644 --- a/Retroactiune.WebAPI/Controllers/FeedbackReceiversController.cs +++ b/Retroactiune.WebAPI/Controllers/FeedbackReceiversController.cs @@ -129,6 +129,7 @@ namespace Retroactiune.Controllers /// The request is invalid. [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status400BadRequest)] public async Task List([FromQuery] IEnumerable filter, [RangeAttribute(1, int.MaxValue, ErrorMessage = "offset is out of range, allowed ranges [1-IntMax]"), FromQuery] @@ -144,7 +145,7 @@ namespace Retroactiune.Controllers /// /// A list of FeedbackReceiver ids. /// The request to delete the items has been submitted. - /// The request is invalid. + /// The request is invalid. /// [HttpDelete] [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] @@ -174,13 +175,14 @@ namespace Retroactiune.Controllers /// The guid of the FeedbackReceiver to add feedback. /// The feedback dto. /// The feedback has been added. - /// The request is invalid. + /// The request is invalid. /// [HttpPost("{guid}/feedbacks")] [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status400BadRequest)] public async Task AddFeedback(string guid, [FromBody] FeedbackInDto feedbackInDto) { + // TODO: Remove guid from request and infer it from the given token. var receivers = await _feedbackReceiversService.FindAsync(new[] {guid}, limit: 1); var tokenEnum = await _tokensService.FindAsync(new TokenListFilters { @@ -218,7 +220,25 @@ namespace Retroactiune.Controllers _feedbacksService.AddFeedbackAsync(feedback, feedbackReceivers[0])); return Ok(); } - - // TODO: Implement get for feedbacks. + + /// + /// Returns the Feedbacks of a FeedbackReceiver. See and . + /// + /// The guid of the FeedbackReceiver. + /// Query filters for filtering the response. + /// The feedback has been added. + /// The request is invalid. + /// + [HttpGet("{guid}/feedbacks")] + [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status400BadRequest)] + public async Task GetFeedbacks(string guid, [FromQuery] ListFeedbacksFiltersDto filters) + { + // TODO: Unit & Integration test. + var feedbacksListFilters = _mapper.Map(filters); + feedbacksListFilters.FeedbackReceiverId = guid; + var response = await _feedbacksService.GetFeedbacksAsync(feedbacksListFilters); + return Ok(response); + } } } \ No newline at end of file diff --git a/Retroactiune.WebAPI/DataTransferObjects/ListFeedbacksFiltersDto.cs b/Retroactiune.WebAPI/DataTransferObjects/ListFeedbacksFiltersDto.cs new file mode 100644 index 0000000..87a1317 --- /dev/null +++ b/Retroactiune.WebAPI/DataTransferObjects/ListFeedbacksFiltersDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace Retroactiune.DataTransferObjects +{ + /// + /// DTO with filters for listing Feedbacks. + /// + public class ListFeedbacksFiltersDto + { + public uint Rating { get; set; } + public DateTime? CreatedAfter { get; set; } + public DateTime? CreatedBefore { get; set; } + } +} \ No newline at end of file diff --git a/Retroactiune.WebAPI/MappingProfile.cs b/Retroactiune.WebAPI/MappingProfile.cs index 0f9a54a..7ff9653 100644 --- a/Retroactiune.WebAPI/MappingProfile.cs +++ b/Retroactiune.WebAPI/MappingProfile.cs @@ -10,6 +10,7 @@ namespace Retroactiune public MappingProfile() { CreateMap(); + CreateMap(); CreateMap().ReverseMap(); CreateMap(); CreateMap();