From 410b2dd77a3b48a9823a4c5cd63a5e0694810baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sun, 4 May 2025 13:49:19 +0200 Subject: [PATCH 1/2] Working endpoint --- .../Tickets/Abstractions/ITicketRepository.cs | 1 + .../Tickets/Abstractions/ITicketService.cs | 2 ++ .../Tickets/Controllers/TicketsController.cs | 17 +++++++++++++++++ .../DTOs/Response/GetTicketForCustomerDto.cs | 8 ++++++++ .../Tickets/Repositories/TicketRepository.cs | 9 +++++++++ .../TickAPI/Tickets/Services/TicketService.cs | 15 +++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketForCustomerDto.cs diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs index ed24346..a09c57d 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs @@ -9,4 +9,5 @@ public interface ITicketRepository public IQueryable GetAllTicketsByTicketType(TicketType ticketType); public Task> GetTicketWithDetailsByIdAndEmailAsync(Guid id, string email); public IQueryable GetTicketsByEventId(Guid eventId); + public IQueryable GetTicketsByCustomerEmail(string email); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs index f705dce..37b6384 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs @@ -11,4 +11,6 @@ public interface ITicketService public Task> GetTicketDetailsAsync(Guid ticketGuid, string email); public Task>> GetTicketsForResellAsync(Guid eventId, int page, int pageSize); + public Task>> GetTicketsForCustomerAsync(string email, int page, + int pageSize); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs index 672368c..78979fb 100644 --- a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs +++ b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs @@ -48,4 +48,21 @@ public async Task>> Ge } return result.Value!; } + + [AuthorizeWithPolicy(AuthPolicies.CustomerPolicy)] + [HttpGet] + public async Task>> GetTicketsForCustomer([FromQuery] int pageSize, [FromQuery] int page) + { + var emailResult = _claimsService.GetEmailFromClaims(User.Claims); + if (emailResult.IsError) + { + return StatusCode(emailResult.StatusCode, emailResult.ErrorMsg); + } + var tickets = await _ticketService.GetTicketsForCustomerAsync(emailResult.Value!, page, pageSize); + if (tickets.IsError) + { + return StatusCode(tickets.StatusCode, tickets.ErrorMsg); + } + return Ok(tickets.Value); + } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketForCustomerDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketForCustomerDto.cs new file mode 100644 index 0000000..ca94458 --- /dev/null +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketForCustomerDto.cs @@ -0,0 +1,8 @@ +namespace TickAPI.Tickets.DTOs.Response; + +public record GetTicketForCustomerDto +( + string EventName, + DateTime EventStartDate, + DateTime EventEndDate +); \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs index c5a6a0d..2ec02c2 100644 --- a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs @@ -28,6 +28,15 @@ public IQueryable GetTicketsByEventId(Guid eventId) .Include(t => t.Type.Event) .Where(t => t.Type.Event.Id == eventId); } + + public IQueryable GetTicketsByCustomerEmail(string email) + { + return _tickApiDbContext.Tickets + .Include(t => t.Owner) + .Include(t => t.Type) + .Include(t =>t.Type.Event) + .Where(t => t.Owner.Email == email); + } public async Task> GetTicketWithDetailsByIdAndEmailAsync(Guid id, string email) { diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index f6c77ac..d003a6e 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -47,6 +47,21 @@ public async Task>> GetTicke t => new GetTicketForResellResponseDto(t.Id, t.Type.Price, t.Type.Currency, t.Type.Description, t.Seats)); return Result>.Success(paginatedResult); } + //TODO: Maybe apply some filtering over here? + public async Task>> GetTicketsForCustomerAsync(string email, int page, int pageSize) + { + var customerTickets = _ticketRepository.GetTicketsByCustomerEmail(email); + var paginatedCustomerTickets = await _paginationService.PaginateAsync(customerTickets, pageSize, page); + if (paginatedCustomerTickets.IsError) + { + return Result>.PropagateError(paginatedCustomerTickets); + } + + var paginatedResult = _paginationService.MapData(paginatedCustomerTickets.Value!, + t => new GetTicketForCustomerDto(t.Type.Event.Name, t.Type.Event.StartDate, t.Type.Event.EndDate)); + + return Result>.Success(paginatedResult); + } public async Task> GetTicketDetailsAsync(Guid ticketGuid, string email) { From 08611621a581275c4ae2040d59b4993ecbaff1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sun, 4 May 2025 14:18:22 +0200 Subject: [PATCH 2/2] Add tests --- .../Tickets/Services/TicketServiceTests.cs | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs index 29c7a2d..479c287 100644 --- a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs @@ -434,4 +434,118 @@ public async Task GetTicketDetailsAsync_WhenTicketDoesNotExistForTheUser_ShouldR Assert.Equal(StatusCodes.Status404NotFound, res.StatusCode); Assert.Equal("Ticket with this id doesn't exist for this user", res.ErrorMsg); } + + [Fact] + public async Task GetTicketsForCustomerAsync_WithValidInput_ReturnsSuccessResult() + { + // Arrange + var email = "test@example.com"; + var page = 0; + var pageSize = 10; + + var tickets = new List + { + new Ticket + { + Type = new TicketType + { + Event = new Event + { + Name = "EventName", + StartDate = new DateTime(2025, 10, 10), + EndDate = new DateTime(2025, 10, 20), + } + } + }, + new Ticket + { + Type = new TicketType + { + Event = new Event + { + Name = "EventName2", + StartDate = new DateTime(2025, 11, 10), + EndDate = new DateTime(2025, 11, 20), + } + } + } + }; + + var paginatedData = new PaginatedData + ( + tickets, + page, + pageSize, + false, + false, + new PaginationDetails(0, 2) + ); + var mappedData1 = new GetTicketForCustomerDto("EventName", new DateTime(2025, 10, 10), new DateTime(2025, 10, 20)); + var mappedData2 = new GetTicketForCustomerDto("EventName2", new DateTime(2025, 11, 10), new DateTime(2025, 11, 20)); + var mappedPaginatedData = new PaginatedData + ( + new List{mappedData1, mappedData2}, + page, + pageSize, + false, + false, + new PaginationDetails(0, 2) + ); + + var ticketRepositoryMock = new Mock(); + ticketRepositoryMock.Setup(r => r.GetTicketsByCustomerEmail(email)).Returns(tickets.AsQueryable()); + + var paginationServiceMock = new Mock(); + paginationServiceMock.Setup(p => p.PaginateAsync(tickets.AsQueryable(), pageSize, page)) + .ReturnsAsync(Result>.Success(paginatedData)); + + paginationServiceMock.Setup(p => p.MapData(paginatedData, It.IsAny>())) + .Returns(mappedPaginatedData); + var sut = new TicketService(ticketRepositoryMock.Object, paginationServiceMock.Object); + + // Act + var result = await sut.GetTicketsForCustomerAsync(email, page, pageSize); + + // Assert + Assert.True(result.IsSuccess); + Assert.Equal(mappedPaginatedData, result.Value); + Assert.Equal(mappedData1, result.Value!.Data[0]); + Assert.Equal(mappedData2, result.Value!.Data[1]); + } + + [Fact] + public async Task GetTicketsForCustomerAsync_WhenUserHasNoTickets_ReturnsEmptyPagination() + { + // Arrange + var email = "empty@example.com"; + var page = 0; + var pageSize = 10; + + var emptyTickets = new List(); + + var emptyPaginatedData = new PaginatedData(emptyTickets, page, pageSize, + false, false, new PaginationDetails(0, 0)); + + var paginatedResult = Result>.Success(emptyPaginatedData); + + var mappedEmptyPaginatedData = new PaginatedData(new List(), + page, pageSize, false, false, new PaginationDetails(0, 0)); + + var ticketRepositoryMock = new Mock(); + ticketRepositoryMock.Setup(r => r.GetTicketsByCustomerEmail(email)).Returns(emptyTickets.AsQueryable()); + + var paginationServiceMock = new Mock(); + paginationServiceMock.Setup(p => p.PaginateAsync(emptyTickets.AsQueryable(), pageSize, page)).ReturnsAsync(paginatedResult); + paginationServiceMock.Setup(p => p.MapData(emptyPaginatedData, It.IsAny>())) + .Returns(mappedEmptyPaginatedData); + + var sut = new TicketService(ticketRepositoryMock.Object, paginationServiceMock.Object); + + // Act + var result = await sut.GetTicketsForCustomerAsync(email, page, pageSize); + + // Assert + Assert.True(result.IsSuccess); + Assert.Empty(result.Value!.Data); + } } \ No newline at end of file