From 54cb5d2d41640779867090a13c09e09bd0816fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 2 May 2025 11:57:56 +0200 Subject: [PATCH 1/7] Check if ticket is assigned to the customer and fetch the ticket --- .../Tickets/Abstractions/ITicketRepository.cs | 6 +++- .../Tickets/Controllers/TicketsController.cs | 10 +++++++ .../Response/GetTicketDetailsResponseDto.cs | 12 ++++++++ .../Tickets/Repositories/TicketRepository.cs | 29 ++++++++++++++++++- .../TickAPI/Tickets/Services/TicketService.cs | 17 +++++++++++ 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs index d3220d8..9edd2b3 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs @@ -1,4 +1,5 @@ -using TickAPI.Tickets.Models; +using TickAPI.Common.Results.Generic; +using TickAPI.Tickets.Models; using TickAPI.TicketTypes.Models; namespace TickAPI.Tickets.Abstractions; @@ -6,4 +7,7 @@ namespace TickAPI.Tickets.Abstractions; public interface ITicketRepository { public IQueryable GetAllTicketsByTicketType(TicketType ticketType); + public Task> CheckIfTicketBelongsToCustomerAsync(Guid id, string email); + + public Task> GetTicketByIdAsync(Guid id); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs index fcf4467..b3ac856 100644 --- a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs +++ b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs @@ -1,4 +1,6 @@ using Microsoft.AspNetCore.Mvc; +using TickAPI.Common.Auth.Attributes; +using TickAPI.Common.Auth.Enums; namespace TickAPI.Tickets.Controllers; @@ -6,5 +8,13 @@ namespace TickAPI.Tickets.Controllers; [Route("api/[controller]")] public class TicketsController : ControllerBase { + public TicketsController() + { + + } + + // [AuthorizeWithPolicy(AuthPolicies.CustomerPolicy)] + // [HttpGet("{id:guid}")] + } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs new file mode 100644 index 0000000..d0ce813 --- /dev/null +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs @@ -0,0 +1,12 @@ +namespace TickAPI.Tickets.DTOs.Response; + +public class GetTicketDetailsResponseDto +{ + public string NameOnTicket { get; set; } + public string? Seats { get; set; } + public bool ForResell { get; set; } + public string EventName {get; set;} + public string OrganizerName {get; set;} + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } +} \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs index 42ade22..df6dd82 100644 --- a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs @@ -1,4 +1,7 @@ -using TickAPI.Common.TickApiDbContext; +using Microsoft.EntityFrameworkCore; +using TickAPI.Common.Results; +using TickAPI.Common.Results.Generic; +using TickAPI.Common.TickApiDbContext; using TickAPI.Tickets.Abstractions; using TickAPI.Tickets.Models; using TickAPI.TicketTypes.Models; @@ -18,4 +21,28 @@ public IQueryable GetAllTicketsByTicketType(TicketType ticketType) { return _tickApiDbContext.Tickets.Where(t => t.Type == ticketType); } + + public async Task> CheckIfTicketBelongsToCustomerAsync(Guid id, string email) + { + var count = await _tickApiDbContext.Tickets.Join(_tickApiDbContext.Customers, + ticket => ticket.Owner.Id, customer => customer.Id, (ticket, customer) => new {ticket.Id}).CountAsync(); + + if (count > 0) + { + return Result.Success(true); + } + + return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist " + + "for this user"); + } + + public async Task> GetTicketByIdAsync(Guid id) + { + var ticket = await _tickApiDbContext.Tickets.FindAsync(id); + if (ticket == null) + { + return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist"); + } + return Result.Success(ticket); + } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index d8d7855..9e0264f 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -1,5 +1,6 @@ using TickAPI.Common.Results.Generic; using TickAPI.Tickets.Abstractions; +using TickAPI.Tickets.DTOs.Response; using TickAPI.TicketTypes.Models; namespace TickAPI.Tickets.Services; @@ -28,4 +29,20 @@ public Result GetNumberOfAvailableTicketsByType(TicketType ticketType) return Result.Success((uint)availableCount); } + + public async Task> GetTicketDetailsAsync(string email, Guid ticketGuid) + { + var exists = await _ticketRepository.CheckIfTicketBelongsToCustomerAsync(ticketGuid, email); + if (!exists.IsSuccess) + { + return Result.PropagateError(exists); + } + + var ticket = await _ticketRepository.GetTicketByIdAsync(ticketGuid); + if (!ticket.IsSuccess) + { + return Result.PropagateError(ticket); + } + + } } \ No newline at end of file From 687bd13a0c2a52b43819ea912a7694176f7d4622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 2 May 2025 15:16:30 +0200 Subject: [PATCH 2/7] Working endpoint --- .../Events/Repositories/EventRepository.cs | 4 ++- .../TickAPI/Events/Services/EventService.cs | 1 + .../Tickets/Abstractions/ITicketService.cs | 2 ++ .../Tickets/Controllers/TicketsController.cs | 32 +++++++++++++++---- .../Response/GetTicketDetailsResponseDto.cs | 3 +- .../Tickets/Repositories/TicketRepository.cs | 3 +- .../TickAPI/Tickets/Services/TicketService.cs | 21 ++++++++++-- 7 files changed, 54 insertions(+), 12 deletions(-) diff --git a/TickAPI/TickAPI/Events/Repositories/EventRepository.cs b/TickAPI/TickAPI/Events/Repositories/EventRepository.cs index 391b613..839c130 100644 --- a/TickAPI/TickAPI/Events/Repositories/EventRepository.cs +++ b/TickAPI/TickAPI/Events/Repositories/EventRepository.cs @@ -1,4 +1,5 @@ -using TickAPI.Common.Results.Generic; +using Microsoft.EntityFrameworkCore; +using TickAPI.Common.Results.Generic; using TickAPI.Common.TickApiDbContext; using TickAPI.Events.Abstractions; using TickAPI.Events.Models; @@ -42,4 +43,5 @@ public Result GetEventById(Guid eventId) return Result.Success(@event); } + } \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 92cbb80..5fedcd6 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -183,4 +183,5 @@ private static GetEventResponseDto MapEventToGetEventResponseDto(Event ev) return new GetEventResponseDto(ev.Id, ev.Name, ev.Description, ev.StartDate, ev.EndDate, ev.MinimumAge, minimumPrice, maximumPrice, categories, ev.EventStatus, address); } + } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs index 85e9ac5..85eb72f 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs @@ -1,4 +1,5 @@ using TickAPI.Common.Results.Generic; +using TickAPI.Tickets.DTOs.Response; using TickAPI.TicketTypes.Models; namespace TickAPI.Tickets.Abstractions; @@ -6,4 +7,5 @@ namespace TickAPI.Tickets.Abstractions; public interface ITicketService { public Result GetNumberOfAvailableTicketsByType(TicketType ticketType); + public Task> GetTicketDetailsAsync(string email, Guid ticketGuid); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs index b3ac856..c0e2998 100644 --- a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs +++ b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs @@ -1,6 +1,9 @@ using Microsoft.AspNetCore.Mvc; using TickAPI.Common.Auth.Attributes; using TickAPI.Common.Auth.Enums; +using TickAPI.Common.Claims.Abstractions; +using TickAPI.Tickets.Abstractions; +using TickAPI.Tickets.DTOs.Response; namespace TickAPI.Tickets.Controllers; @@ -8,13 +11,30 @@ namespace TickAPI.Tickets.Controllers; [Route("api/[controller]")] public class TicketsController : ControllerBase { - public TicketsController() + private readonly IClaimsService _claimsService; + private readonly ITicketService _ticketService; + public TicketsController(IClaimsService claimsService, ITicketService ticketService) { - + _claimsService = claimsService; + _ticketService = ticketService; + } + + [AuthorizeWithPolicy(AuthPolicies.CustomerPolicy)] + [HttpGet("{id:guid}")] + public async Task> GetTicketDetails(Guid id) + { + var emailResult = _claimsService.GetEmailFromClaims(User.Claims); + if (emailResult.IsError) + { + return StatusCode(emailResult.StatusCode, emailResult.ErrorMsg); + } + var email = emailResult.Value!; + var ticket = await _ticketService.GetTicketDetailsAsync(email, id); + if (!ticket.IsSuccess) + { + return StatusCode(ticket.StatusCode, ticket.ErrorMsg); + } + return Ok(ticket.Value); } - - // [AuthorizeWithPolicy(AuthPolicies.CustomerPolicy)] - // [HttpGet("{id:guid}")] - } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs index d0ce813..a0c6423 100644 --- a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs @@ -4,7 +4,8 @@ public class GetTicketDetailsResponseDto { public string NameOnTicket { get; set; } public string? Seats { get; set; } - public bool ForResell { get; set; } + public decimal Price { get; set; } + public string Currency { get; set; } public string EventName {get; set;} public string OrganizerName {get; set;} public DateTime StartDate { get; set; } diff --git a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs index df6dd82..89d0bf5 100644 --- a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs @@ -38,7 +38,8 @@ public async Task> CheckIfTicketBelongsToCustomerAsync(Guid id, str public async Task> GetTicketByIdAsync(Guid id) { - var ticket = await _tickApiDbContext.Tickets.FindAsync(id); + var ticket = await _tickApiDbContext.Tickets.Include(t => t.Type).Include(t => t.Type.Event) + .Include(t => t.Type.Event.Organizer).FirstOrDefaultAsync(); if (ticket == null) { return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist"); diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index 9e0264f..3cd03fc 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -3,6 +3,7 @@ using TickAPI.Tickets.DTOs.Response; using TickAPI.TicketTypes.Models; + namespace TickAPI.Tickets.Services; public class TicketService : ITicketService @@ -38,11 +39,25 @@ public async Task> GetTicketDetailsAsync(str return Result.PropagateError(exists); } - var ticket = await _ticketRepository.GetTicketByIdAsync(ticketGuid); - if (!ticket.IsSuccess) + var ticketRes = await _ticketRepository.GetTicketByIdAsync(ticketGuid); + if (!ticketRes.IsSuccess) { - return Result.PropagateError(ticket); + return Result.PropagateError(ticketRes); } + var ticket = ticketRes.Value; + var ticketDetails = new GetTicketDetailsResponseDto + { + NameOnTicket = ticket.NameOnTicket, + Seats = ticket.Seats, + Price = ticket.Type.Price, + Currency = ticket.Type.Currency, + EventName = ticket.Type.Event.Name, + OrganizerName = ticket.Type.Event.Organizer.DisplayName, + StartDate = ticket.Type.Event.StartDate, + EndDate = ticket.Type.Event.EndDate, + }; + return Result.Success(ticketDetails); + } } \ No newline at end of file From fc28f01c70f2770fb760c8df31b64ac18c12f6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Fri, 2 May 2025 15:33:24 +0200 Subject: [PATCH 3/7] Add address --- .../DTOs/Response/GetTicketDetailsAddressDto.cs | 10 ++++++++++ .../DTOs/Response/GetTicketDetailsResponseDto.cs | 6 +++++- .../TickAPI/Tickets/Repositories/TicketRepository.cs | 3 ++- TickAPI/TickAPI/Tickets/Services/TicketService.cs | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsAddressDto.cs diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsAddressDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsAddressDto.cs new file mode 100644 index 0000000..c6dd05c --- /dev/null +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsAddressDto.cs @@ -0,0 +1,10 @@ +namespace TickAPI.Tickets.DTOs.Response; + +public record GetTicketDetailsAddressDto( + string Country, + string City, + string PostalCode, + string? Street, + uint? HouseNumber, + uint? FlatNumber +); \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs index a0c6423..72adbd9 100644 --- a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs @@ -1,4 +1,6 @@ -namespace TickAPI.Tickets.DTOs.Response; +using TickAPI.Addresses.Models; + +namespace TickAPI.Tickets.DTOs.Response; public class GetTicketDetailsResponseDto { @@ -10,4 +12,6 @@ public class GetTicketDetailsResponseDto public string OrganizerName {get; set;} public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } + + public GetTicketDetailsAddressDto Address { get; set; } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs index 89d0bf5..678bb4e 100644 --- a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs @@ -39,7 +39,8 @@ public async Task> CheckIfTicketBelongsToCustomerAsync(Guid id, str public async Task> GetTicketByIdAsync(Guid id) { var ticket = await _tickApiDbContext.Tickets.Include(t => t.Type).Include(t => t.Type.Event) - .Include(t => t.Type.Event.Organizer).FirstOrDefaultAsync(); + .Include(t => t.Type.Event.Organizer). + Include(t => t.Type.Event.Address).FirstOrDefaultAsync(); if (ticket == null) { return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist"); diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index 3cd03fc..8b381ec 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -45,6 +45,9 @@ public async Task> GetTicketDetailsAsync(str return Result.PropagateError(ticketRes); } var ticket = ticketRes.Value; + var ev = ticket.Type.Event; + var address = new GetTicketDetailsAddressDto(ev.Address.Country, ev.Address.City, ev.Address.PostalCode, + ev.Address.Street, ev.Address.HouseNumber, ev.Address.FlatNumber); var ticketDetails = new GetTicketDetailsResponseDto { NameOnTicket = ticket.NameOnTicket, @@ -55,6 +58,8 @@ public async Task> GetTicketDetailsAsync(str OrganizerName = ticket.Type.Event.Organizer.DisplayName, StartDate = ticket.Type.Event.StartDate, EndDate = ticket.Type.Event.EndDate, + Address = address, + }; return Result.Success(ticketDetails); From 8a74425ca674b91284bd6183eec9b845aa7a6283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sat, 3 May 2025 09:50:08 +0200 Subject: [PATCH 4/7] Add unit tests --- .../Tickets/Services/TicketServiceTests.cs | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs index 068a29f..6270cbf 100644 --- a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs @@ -1,7 +1,13 @@ using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Moq; +using TickAPI.Addresses.Models; using TickAPI.Common.Results.Generic; +using TickAPI.Customers.Models; +using TickAPI.Events.Models; +using TickAPI.Organizers.Models; using TickAPI.Tickets.Abstractions; +using TickAPI.Tickets.DTOs.Response; using TickAPI.Tickets.Models; using TickAPI.Tickets.Services; using TickAPI.TicketTypes.Models; @@ -56,4 +62,103 @@ public void GetNumberOfAvailableTicketsByType_WhenMoreTicketExistThanMaxCount_Sh Assert.Equal(StatusCodes.Status500InternalServerError, result.StatusCode); Assert.Equal("The number of available tickets is negative.", result.ErrorMsg); } + + [Fact] + public async Task GetTicketDetailsAsync_WhenTicketExistsForTheUser_ShouldReturnTicketDetails() + { + + // Arrange + var ticket = new Ticket + { + Id = Guid.NewGuid(), + ForResell = false, + NameOnTicket = "NameOnTicket", + Seats = null, + Type = new TicketType + { + Currency = "USD", + Price = 20, + Event = new Event + { + Name = "EventName", + StartDate = new DateTime(2025, 10, 10), + EndDate = new DateTime(2025, 10, 20), + Organizer = new Organizer + { + DisplayName = "organizerName", + }, + Address = new Address + { + City = "Warsaw", + Country = "Poland", + PostalCode = "12345", + FlatNumber = null, + HouseNumber = null, + Street = "Street", + } + } + }, + }; + string email = "123@123.com"; + + Mock ticketRepositoryMock = new Mock(); + ticketRepositoryMock.Setup(m => + m.CheckIfTicketBelongsToCustomerAsync(ticket.Id, email)).ReturnsAsync(Result.Success(true)); + + ticketRepositoryMock.Setup(m => m.GetTicketByIdAsync(ticket.Id)).ReturnsAsync(Result.Success(ticket)); + + var sut = new TicketService(ticketRepositoryMock.Object); + + // Act + + var res = await sut.GetTicketDetailsAsync(email, ticket.Id); + + // Assert + + Assert.True(res.IsSuccess); + var details = res.Value; + Assert.NotNull(details); + + Assert.Equal(ticket.NameOnTicket, details.NameOnTicket); + Assert.Equal(ticket.Seats, details.Seats); + Assert.Equal(ticket.Type.Currency, details.Currency); + Assert.Equal(ticket.Type.Price, details.Price); + Assert.Equal(ticket.Type.Event.StartDate, details.StartDate); + Assert.Equal(ticket.Type.Event.EndDate, details.EndDate); + Assert.Equal(ticket.Type.Event.Organizer.DisplayName, details.OrganizerName); + Assert.Equal(ticket.Type.Event.Address.Street, details.Address.Street); + Assert.Equal(ticket.Type.Event.Address.HouseNumber, details.Address.HouseNumber); + Assert.Equal(ticket.Type.Event.Address.FlatNumber, details.Address.FlatNumber); + Assert.Equal(ticket.Type.Event.Address.PostalCode, details.Address.PostalCode); + Assert.Equal(ticket.Type.Event.Address.City, details.Address.City); + Assert.Equal(ticket.Type.Event.Address.Country, details.Address.Country); + + } + + [Fact] + public async Task GetTicketDetailsAsync_WhenTicketDoesntExistsForTheUser_ShouldReturnError() + { + + // Arrange + + Guid ticketId = Guid.NewGuid(); + string email = "123@123.com"; + + Mock ticketRepositoryMock = new Mock(); + ticketRepositoryMock.Setup(m => m.CheckIfTicketBelongsToCustomerAsync(ticketId, email)). + ReturnsAsync(Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist " + + "for this user")); + + var sut = new TicketService(ticketRepositoryMock.Object); + + // Act + + var res = await sut.GetTicketDetailsAsync(email, ticketId); + + // Assert + + Assert.False(res.IsSuccess); + Assert.Equal(StatusCodes.Status404NotFound, res.StatusCode); + Assert.Equal("Ticket with this id doesn't exist for this user", res.ErrorMsg); + } } \ No newline at end of file From dd952cea6555a195fc869e1e741bd3da50972983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sat, 3 May 2025 15:09:28 +0200 Subject: [PATCH 5/7] Fixes from review --- .../Tickets/Services/TicketServiceTests.cs | 15 ++++---- .../Events/Repositories/EventRepository.cs | 1 - .../TickAPI/Events/Services/EventService.cs | 1 - .../Tickets/Abstractions/ITicketRepository.cs | 3 +- .../Tickets/Abstractions/ITicketService.cs | 5 ++- .../Tickets/Controllers/TicketsController.cs | 2 +- .../Response/GetTicketDetailsResponseDto.cs | 26 +++++++------- .../Tickets/Repositories/TicketRepository.cs | 24 +++---------- .../TickAPI/Tickets/Services/TicketService.cs | 36 ++++++++----------- 9 files changed, 43 insertions(+), 70 deletions(-) diff --git a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs index 9b56530..3b4c3db 100644 --- a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs @@ -337,6 +337,7 @@ public async Task GetTicketDetailsAsync_WhenTicketExistsForTheUser_ShouldReturnT { // Arrange + var eventGuid = Guid.NewGuid(); var ticket = new Ticket { Id = Guid.NewGuid(), @@ -345,6 +346,7 @@ public async Task GetTicketDetailsAsync_WhenTicketExistsForTheUser_ShouldReturnT Seats = null, Type = new TicketType { + Id = eventGuid, Currency = "USD", Price = 20, Event = new Event @@ -371,18 +373,17 @@ public async Task GetTicketDetailsAsync_WhenTicketExistsForTheUser_ShouldReturnT string email = "123@123.com"; Mock ticketRepositoryMock = new Mock(); - ticketRepositoryMock.Setup(m => - m.CheckIfTicketBelongsToCustomerAsync(ticket.Id, email)).ReturnsAsync(Result.Success(true)); var paginationServiceMock = new Mock(); - ticketRepositoryMock.Setup(m => m.GetTicketByIdAsync(ticket.Id)).ReturnsAsync(Result.Success(ticket)); + ticketRepositoryMock.Setup(m => m.GetTicketWithDetailsByIdAndEmailAsync(ticket.Id, email)) + .ReturnsAsync(Result.Success(ticket)); var sut = new TicketService(ticketRepositoryMock.Object, paginationServiceMock.Object); // Act - var res = await sut.GetTicketDetailsAsync(email, ticket.Id); + var res = await sut.GetTicketDetailsAsync(ticket.Id, email); // Assert @@ -416,8 +417,8 @@ public async Task GetTicketDetailsAsync_WhenTicketDoesntExistsForTheUser_ShouldR string email = "123@123.com"; Mock ticketRepositoryMock = new Mock(); - ticketRepositoryMock.Setup(m => m.CheckIfTicketBelongsToCustomerAsync(ticketId, email)). - ReturnsAsync(Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist " + + ticketRepositoryMock.Setup(m => m.GetTicketWithDetailsByIdAndEmailAsync(ticketId, email)). + ReturnsAsync(Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist " + "for this user")); var paginationServiceMock = new Mock(); @@ -425,7 +426,7 @@ public async Task GetTicketDetailsAsync_WhenTicketDoesntExistsForTheUser_ShouldR // Act - var res = await sut.GetTicketDetailsAsync(email, ticketId); + var res = await sut.GetTicketDetailsAsync(ticketId, email); // Assert diff --git a/TickAPI/TickAPI/Events/Repositories/EventRepository.cs b/TickAPI/TickAPI/Events/Repositories/EventRepository.cs index c151d62..bdc59ee 100644 --- a/TickAPI/TickAPI/Events/Repositories/EventRepository.cs +++ b/TickAPI/TickAPI/Events/Repositories/EventRepository.cs @@ -54,5 +54,4 @@ public async Task> GetEventByIdAsync(Guid eventId) return Result.Success(@event); } - } \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index a226bd9..201a9a9 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -199,5 +199,4 @@ private static GetEventResponseDto MapEventToGetEventResponseDto(Event ev) return new GetEventResponseDto(ev.Id, ev.Name, ev.Description, ev.StartDate, ev.EndDate, ev.MinimumAge, minimumPrice, maximumPrice, categories, ev.EventStatus, address); } - } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs index f0a4733..93e313f 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs @@ -7,8 +7,7 @@ namespace TickAPI.Tickets.Abstractions; public interface ITicketRepository { public IQueryable GetAllTicketsByTicketType(TicketType ticketType); - public Task> CheckIfTicketBelongsToCustomerAsync(Guid id, string email); - public Task> GetTicketByIdAsync(Guid id); + public Task> GetTicketWithDetailsByIdAndEmailAsync(Guid id, string email); public IQueryable GetTicketsByEventId(Guid eventId); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs index dd63ef9..f705dce 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketService.cs @@ -8,8 +8,7 @@ namespace TickAPI.Tickets.Abstractions; public interface ITicketService { public Result GetNumberOfAvailableTicketsByType(TicketType ticketType); - public Task> GetTicketDetailsAsync(string email, Guid ticketGuid); - - Task>> GetTicketsForResellAsync(Guid eventId, int page, + public Task> GetTicketDetailsAsync(Guid ticketGuid, string email); + public Task>> GetTicketsForResellAsync(Guid eventId, 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 82f7d25..dfc56b0 100644 --- a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs +++ b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs @@ -32,7 +32,7 @@ public async Task> GetTicketDetails(Gu return StatusCode(emailResult.StatusCode, emailResult.ErrorMsg); } var email = emailResult.Value!; - var ticket = await _ticketService.GetTicketDetailsAsync(email, id); + var ticket = await _ticketService.GetTicketDetailsAsync(id, email); if (!ticket.IsSuccess) { return StatusCode(ticket.StatusCode, ticket.ErrorMsg); diff --git a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs index 72adbd9..46032d5 100644 --- a/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs +++ b/TickAPI/TickAPI/Tickets/DTOs/Response/GetTicketDetailsResponseDto.cs @@ -2,16 +2,16 @@ namespace TickAPI.Tickets.DTOs.Response; -public class GetTicketDetailsResponseDto -{ - public string NameOnTicket { get; set; } - public string? Seats { get; set; } - public decimal Price { get; set; } - public string Currency { get; set; } - public string EventName {get; set;} - public string OrganizerName {get; set;} - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } - - public GetTicketDetailsAddressDto Address { get; set; } -} \ No newline at end of file +public record GetTicketDetailsResponseDto +( + string NameOnTicket, + string? Seats, + decimal Price, + string Currency, + string EventName, + string OrganizerName, + DateTime StartDate, + DateTime EndDate, + GetTicketDetailsAddressDto Address, + Guid eventId +); \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs index 8e1e60a..c5a6a0d 100644 --- a/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Repositories/TicketRepository.cs @@ -1,7 +1,5 @@ using Microsoft.EntityFrameworkCore; -using TickAPI.Common.Results; using TickAPI.Common.Results.Generic; -using Microsoft.EntityFrameworkCore; using TickAPI.Common.TickApiDbContext; using TickAPI.Tickets.Abstractions; using TickAPI.Tickets.Models; @@ -30,26 +28,12 @@ public IQueryable GetTicketsByEventId(Guid eventId) .Include(t => t.Type.Event) .Where(t => t.Type.Event.Id == eventId); } - - public async Task> CheckIfTicketBelongsToCustomerAsync(Guid id, string email) - { - var count = await _tickApiDbContext.Tickets.Join(_tickApiDbContext.Customers, - ticket => ticket.Owner.Id, customer => customer.Id, (ticket, customer) => new {ticket.Id}).CountAsync(); - - if (count > 0) - { - return Result.Success(true); - } - - return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist " + - "for this user"); - } - - public async Task> GetTicketByIdAsync(Guid id) + + public async Task> GetTicketWithDetailsByIdAndEmailAsync(Guid id, string email) { var ticket = await _tickApiDbContext.Tickets.Include(t => t.Type).Include(t => t.Type.Event) - .Include(t => t.Type.Event.Organizer). - Include(t => t.Type.Event.Address).FirstOrDefaultAsync(); + .Include(t => t.Type.Event.Organizer).Include(t => t.Type.Event.Address) + .Where(t => (t.Id == id && t.Owner.Email == email)).FirstOrDefaultAsync(); if (ticket == null) { return Result.Failure(StatusCodes.Status404NotFound, "Ticket with this id doesn't exist"); diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index 6c85849..6843b04 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -48,15 +48,9 @@ public async Task>> GetTicke return Result>.Success(paginatedResult); } - public async Task> GetTicketDetailsAsync(string email, Guid ticketGuid) + public async Task> GetTicketDetailsAsync(Guid ticketGuid, string email) { - var exists = await _ticketRepository.CheckIfTicketBelongsToCustomerAsync(ticketGuid, email); - if (!exists.IsSuccess) - { - return Result.PropagateError(exists); - } - - var ticketRes = await _ticketRepository.GetTicketByIdAsync(ticketGuid); + var ticketRes = await _ticketRepository.GetTicketWithDetailsByIdAndEmailAsync(ticketGuid, email); if (!ticketRes.IsSuccess) { return Result.PropagateError(ticketRes); @@ -66,20 +60,18 @@ public async Task> GetTicketDetailsAsync(str var address = new GetTicketDetailsAddressDto(ev.Address.Country, ev.Address.City, ev.Address.PostalCode, ev.Address.Street, ev.Address.HouseNumber, ev.Address.FlatNumber); var ticketDetails = new GetTicketDetailsResponseDto - { - NameOnTicket = ticket.NameOnTicket, - Seats = ticket.Seats, - Price = ticket.Type.Price, - Currency = ticket.Type.Currency, - EventName = ticket.Type.Event.Name, - OrganizerName = ticket.Type.Event.Organizer.DisplayName, - StartDate = ticket.Type.Event.StartDate, - EndDate = ticket.Type.Event.EndDate, - Address = address, - - }; - + ( + ticket.NameOnTicket, + ticket.Seats, + ticket.Type.Price, + ticket.Type.Currency, + ticket.Type.Event.Name, + ticket.Type.Event.Organizer.DisplayName, + ticket.Type.Event.StartDate, + ticket.Type.Event.EndDate, + address, + ticket.Type.Event.Id + ); return Result.Success(ticketDetails); - } } \ No newline at end of file From 8ce7ff43ae3de09c1065f019a74be1faaf830e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sat, 3 May 2025 17:42:24 +0200 Subject: [PATCH 6/7] Dont even want to comment on it --- TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs index dfc56b0..672368c 100644 --- a/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs +++ b/TickAPI/TickAPI/Tickets/Controllers/TicketsController.cs @@ -5,8 +5,6 @@ using TickAPI.Tickets.Abstractions; using TickAPI.Tickets.DTOs.Response; using TickAPI.Common.Pagination.Responses; -using TickAPI.Tickets.Abstractions; -using TickAPI.Tickets.DTOs.Response; namespace TickAPI.Tickets.Controllers; @@ -33,7 +31,7 @@ public async Task> GetTicketDetails(Gu } var email = emailResult.Value!; var ticket = await _ticketService.GetTicketDetailsAsync(id, email); - if (!ticket.IsSuccess) + if (ticket.IsError) { return StatusCode(ticket.StatusCode, ticket.ErrorMsg); } From 2bb7179b71a9f94621c3846aa24b2e7702bd10b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sat, 3 May 2025 19:11:17 +0200 Subject: [PATCH 7/7] Dont want to comment on it even harder --- TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs | 2 +- TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs | 1 - TickAPI/TickAPI/Tickets/Services/TicketService.cs | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs index 3b4c3db..29c7a2d 100644 --- a/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Tickets/Services/TicketServiceTests.cs @@ -408,7 +408,7 @@ public async Task GetTicketDetailsAsync_WhenTicketExistsForTheUser_ShouldReturnT } [Fact] - public async Task GetTicketDetailsAsync_WhenTicketDoesntExistsForTheUser_ShouldReturnError() + public async Task GetTicketDetailsAsync_WhenTicketDoesNotExistForTheUser_ShouldReturnError() { // Arrange diff --git a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs index 93e313f..ed24346 100644 --- a/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs +++ b/TickAPI/TickAPI/Tickets/Abstractions/ITicketRepository.cs @@ -7,7 +7,6 @@ namespace TickAPI.Tickets.Abstractions; public interface ITicketRepository { public IQueryable GetAllTicketsByTicketType(TicketType ticketType); - public Task> GetTicketWithDetailsByIdAndEmailAsync(Guid id, string email); public IQueryable GetTicketsByEventId(Guid eventId); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Tickets/Services/TicketService.cs b/TickAPI/TickAPI/Tickets/Services/TicketService.cs index 6843b04..f6c77ac 100644 --- a/TickAPI/TickAPI/Tickets/Services/TicketService.cs +++ b/TickAPI/TickAPI/Tickets/Services/TicketService.cs @@ -51,11 +51,11 @@ public async Task>> GetTicke public async Task> GetTicketDetailsAsync(Guid ticketGuid, string email) { var ticketRes = await _ticketRepository.GetTicketWithDetailsByIdAndEmailAsync(ticketGuid, email); - if (!ticketRes.IsSuccess) + if (ticketRes.IsError) { return Result.PropagateError(ticketRes); } - var ticket = ticketRes.Value; + var ticket = ticketRes.Value!; var ev = ticket.Type.Event; var address = new GetTicketDetailsAddressDto(ev.Address.Country, ev.Address.City, ev.Address.PostalCode, ev.Address.Street, ev.Address.HouseNumber, ev.Address.FlatNumber);