From 282c995c39fc3b0c658c763dfa3d4f2afeca3b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Mon, 14 Apr 2025 13:57:00 +0200 Subject: [PATCH 01/15] resolve merge conflicts --- .../Controllers/EventControllerTests.cs | 20 ++++-- .../Events/Services/EventServiceTests.cs | 66 ++++++++++++++----- .../DTOs/Request/CreateEventCategoryDto.cs | 6 ++ .../Events/Abstractions/IEventService.cs | 4 +- .../Events/Controllers/EventController.cs | 4 +- .../Events/DTOs/Request/CreateEventDto.cs | 5 +- .../TickAPI/Events/Services/EventService.cs | 22 ++++++- 7 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 TickAPI/TickAPI/Categories/DTOs/Request/CreateEventCategoryDto.cs diff --git a/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs b/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs index 8c788b1..c1f2947 100644 --- a/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using TickAPI.Addresses.DTOs.Request; +using TickAPI.Categories.DTOs.Request; using TickAPI.Common.Claims.Abstractions; using TickAPI.Common.Pagination.Responses; using TickAPI.Events.Controllers; @@ -30,12 +31,17 @@ public async Task CreateEvent_WhenDataIsValid_ShouldReturnSuccess() const string email = "123@mail.com"; const EventStatus eventStatus = EventStatus.TicketsAvailable; Guid id = Guid.NewGuid(); + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); - CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, eventStatus, createAddress); + CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, eventStatus, createAddress); var eventServiceMock = new Mock(); eventServiceMock - .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, eventStatus, email)) + .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories ,eventStatus, email)) .ReturnsAsync(Result.Success(new Event())); var claims = new List @@ -79,6 +85,12 @@ public async Task CreateEvent_WhenMissingEmailClaims_ShouldReturnBadRequest() DateTime endDate = new DateTime(2025, 6, 1); uint? minimumAge = 18; const EventStatus eventStatus = EventStatus.TicketsAvailable; + string email = "123@mail.com"; + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventServiceMock = new Mock(); @@ -97,8 +109,8 @@ public async Task CreateEvent_WhenMissingEmailClaims_ShouldReturnBadRequest() } }; - // Act - var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, eventStatus, createAddress)); + // act + var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, eventStatus, createAddress)); // Assert var result = Assert.IsType>(res); diff --git a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs index 59bdd8a..a14f429 100644 --- a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs @@ -6,6 +6,8 @@ using TickAPI.Addresses.Models; using TickAPI.Common.Pagination.Abstractions; using TickAPI.Common.Pagination.Responses; +using TickAPI.Categories.Abstractions; +using TickAPI.Categories.DTOs.Request; using TickAPI.Events.Models; using TickAPI.Organizers.Abstractions; using TickAPI.Organizers.Models; @@ -31,6 +33,11 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( string organizerEmail = "123@mail.com"; EventStatus eventStatus = EventStatus.TicketsAvailable; Guid id = Guid.NewGuid(); + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -57,13 +64,14 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( var dateTimeServiceMock = new Mock(); dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2003, 7, 11)); + + var categoryRepositoryMock = new Mock(); var paginationServiceMock = new Mock(); - - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object); - // Act - var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, eventStatus, organizerEmail); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + // act + var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); // Assert Assert.True(result.IsSuccess); @@ -88,6 +96,11 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB string organizerEmail = "123@mail.com"; EventStatus eventStatus = EventStatus.TicketsAvailable; Guid id = Guid.NewGuid(); + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -100,13 +113,16 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); - + + var categoryRepositoryMock = new Mock(); + + + // act var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); - // Act - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); // Assert Assert.False(res.IsSuccess); @@ -125,6 +141,12 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe uint? minimumAge = 18; string organizerEmail = "123@mail.com"; EventStatus eventStatus = EventStatus.TicketsAvailable; + Guid id = Guid.NewGuid(); + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -138,13 +160,15 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe var dateTimeServiceMock = new Mock(); dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2025, 5, 11)); - + + var categoryRepositoryMock = new Mock(); + + // act var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); - // Act - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); // Assert Assert.False(res.IsSuccess); @@ -175,6 +199,7 @@ public async Task GetOrganizerEvents_WhenPaginationSucceeds_ShouldReturnPaginate var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var paginatedEvents = new PaginatedData( organizer.Events.Take(pageSize).ToList(), @@ -208,7 +233,7 @@ public async Task GetOrganizerEvents_WhenPaginationSucceeds_ShouldReturnPaginate )); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -248,6 +273,7 @@ public async Task GetOrganizerEvents_WhenPaginationFails_ShouldPropagateError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var organizerEvents = organizer.Events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEventsByOranizer(organizer)).Returns(organizerEvents); @@ -257,7 +283,7 @@ public async Task GetOrganizerEvents_WhenPaginationFails_ShouldPropagateError() .ReturnsAsync(Result>.Failure(StatusCodes.Status400BadRequest, "Invalid page number")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -286,6 +312,7 @@ public async Task GetEventsAsync_WhenPaginationSucceeds_ShouldReturnPaginatedEve var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var paginatedEvents = new PaginatedData( events.Take(pageSize).ToList(), @@ -319,7 +346,7 @@ public async Task GetEventsAsync_WhenPaginationSucceeds_ShouldReturnPaginatedEve )); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -354,6 +381,7 @@ public async Task GetEventsAsync_WhenPaginationFails_ShouldPropagateError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -363,7 +391,7 @@ public async Task GetEventsAsync_WhenPaginationFails_ShouldPropagateError() .ReturnsAsync(Result>.Failure(StatusCodes.Status400BadRequest, "Invalid page number")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -391,6 +419,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenSuccessful_ShouldReturnPag var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -401,7 +430,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenSuccessful_ShouldReturnPag .ReturnsAsync(Result.Success(paginationDetails)); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); @@ -428,6 +457,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenFails_ShouldReturnError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); + var categoryRepositoryMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -437,7 +467,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenFails_ShouldReturnError() .ReturnsAsync(Result.Failure(StatusCodes.Status400BadRequest, "Invalid page size")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); diff --git a/TickAPI/TickAPI/Categories/DTOs/Request/CreateEventCategoryDto.cs b/TickAPI/TickAPI/Categories/DTOs/Request/CreateEventCategoryDto.cs new file mode 100644 index 0000000..8e696d7 --- /dev/null +++ b/TickAPI/TickAPI/Categories/DTOs/Request/CreateEventCategoryDto.cs @@ -0,0 +1,6 @@ +namespace TickAPI.Categories.DTOs.Request; + +public record CreateEventCategoryDto +( + string CategoryName +); \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs index 8afbaad..b2267ba 100644 --- a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs +++ b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs @@ -1,5 +1,6 @@ using TickAPI.Addresses.DTOs.Request; using TickAPI.Common.Pagination.Responses; +using TickAPI.Categories.DTOs.Request; using TickAPI.Events.Models; using TickAPI.Common.Results.Generic; using TickAPI.Events.DTOs.Response; @@ -10,7 +11,8 @@ namespace TickAPI.Events.Abstractions; public interface IEventService { public Task> CreateNewEventAsync(string name, string description, DateTime startDate, - DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, EventStatus eventStatus, string organizerEmail); + DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, List categories + ,EventStatus eventStatus, string organizerEmail); public Task>> GetOrganizerEventsAsync(Organizer organizer, int page, int pageSize); public Task> GetOrganizerEventsPaginationDetailsAsync(Organizer organizer, int pageSize); public Task>> GetEventsAsync(int page, int pageSize); diff --git a/TickAPI/TickAPI/Events/Controllers/EventController.cs b/TickAPI/TickAPI/Events/Controllers/EventController.cs index 5ea6f4e..f368926 100644 --- a/TickAPI/TickAPI/Events/Controllers/EventController.cs +++ b/TickAPI/TickAPI/Events/Controllers/EventController.cs @@ -38,7 +38,9 @@ public async Task> CreateEvent([FromBody] C } var email = emailResult.Value!; - var newEventResult = await _eventService.CreateNewEventAsync(request.Name, request.Description, request.StartDate, request.EndDate, request.MinimumAge, request.CreateAddress, request.EventStatus, email); + var newEventResult = await _eventService.CreateNewEventAsync(request.Name, request.Description, + request.StartDate, request.EndDate, request.MinimumAge, request.CreateAddress, request.Categories + ,request.EventStatus, email); if (newEventResult.IsError) return StatusCode(newEventResult.StatusCode, newEventResult.ErrorMsg); diff --git a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs index 1078587..01bb591 100644 --- a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs +++ b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs @@ -1,15 +1,16 @@ using TickAPI.Events.Models; using TickAPI.Addresses.DTOs.Request; +using TickAPI.Categories.DTOs.Request; namespace TickAPI.Events.DTOs.Request; -public record CreateEventDto -( +public record CreateEventDto( string Name, string Description, DateTime StartDate, DateTime EndDate, uint? MinimumAge, + List Categories, EventStatus EventStatus, CreateAddressDto CreateAddress ); \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 6ac130c..30c7d8b 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -2,6 +2,9 @@ using TickAPI.Addresses.DTOs.Request; using TickAPI.Common.Pagination.Abstractions; using TickAPI.Common.Pagination.Responses; +using TickAPI.Categories.Abstractions; +using TickAPI.Categories.DTOs.Request; +using TickAPI.Categories.Models; using TickAPI.Common.Time.Abstractions; using TickAPI.Events.Abstractions; using TickAPI.Events.Models; @@ -19,17 +22,21 @@ public class EventService : IEventService private readonly IAddressService _addressService; private readonly IDateTimeService _dateTimeService; private readonly IPaginationService _paginationService; + private readonly ICategoryRepository _categoryRepository; - public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService) + public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryRepository categoryRepository) { _eventRepository = eventRepository; _organizerService = organizerService; _addressService = addressService; _dateTimeService = dateTimeService; _paginationService = paginationService; + _categoryRepository = categoryRepository; } - public async Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, EventStatus eventStatus, string organizerEmail) + public async Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, + uint? minimumAge, CreateAddressDto createAddress, List categories, + EventStatus eventStatus, string organizerEmail) { var organizerResult = await _organizerService.GetOrganizerByEmailAsync(organizerEmail); if (!organizerResult.IsSuccess) @@ -44,6 +51,16 @@ public async Task> CreateNewEventAsync(string name, string descri var address = await _addressService.GetOrCreateAddressAsync(createAddress); + + var categoriesConverted = new List(); + + foreach (var c in categories) + { + categoriesConverted.Add(new Category + { + Name = c.CategoryName + }); + } var @event = new Event { @@ -53,6 +70,7 @@ public async Task> CreateNewEventAsync(string name, string descri EndDate = endDate, MinimumAge = minimumAge, Address = address.Value!, + Categories = categoriesConverted, Organizer = organizerResult.Value!, EventStatus = eventStatus }; From 027aec05366468b6238a10995d83ee84ed449563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:33:52 +0200 Subject: [PATCH 02/15] Check if categories exist --- .../TickAPI/Categories/Abstractions/ICategoryRepository.cs | 2 ++ .../Categories/DTOs/{ => Request}/CreateCategoryDto.cs | 0 .../TickAPI/Categories/Respositories/CategoryRepository.cs | 6 ++++++ TickAPI/TickAPI/Events/Services/EventService.cs | 6 ++++++ 4 files changed, 14 insertions(+) rename TickAPI/TickAPI/Categories/DTOs/{ => Request}/CreateCategoryDto.cs (100%) diff --git a/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs b/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs index c7d1fc3..9e6e598 100644 --- a/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs +++ b/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs @@ -8,4 +8,6 @@ public interface ICategoryRepository public IQueryable GetCategories(); public Task> GetCategoryByNameAsync(string categoryName); public Task AddNewCategoryAsync(Category category); + + public Task CheckIfCategoriesExistAsync(List categories); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Categories/DTOs/CreateCategoryDto.cs b/TickAPI/TickAPI/Categories/DTOs/Request/CreateCategoryDto.cs similarity index 100% rename from TickAPI/TickAPI/Categories/DTOs/CreateCategoryDto.cs rename to TickAPI/TickAPI/Categories/DTOs/Request/CreateCategoryDto.cs diff --git a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs index e1dcdb2..4360419 100644 --- a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs +++ b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs @@ -31,6 +31,12 @@ public async Task> GetCategoryByNameAsync(string categoryName) return Result.Success(category); } + public async Task CheckIfCategoriesExistAsync(List categories) + { + var dbCategories = await _tickApiDbContext.Categories.ToListAsync(); + return categories.All(c => dbCategories.Contains(c)); + } + public async Task AddNewCategoryAsync(Category category) { _tickApiDbContext.Categories.Add(category); diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 30c7d8b..837da66 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -61,6 +61,12 @@ public async Task> CreateNewEventAsync(string name, string descri Name = c.CategoryName }); } + + var categoriesExist = await _categoryRepository.CheckIfCategoriesExistAsync(categoriesConverted); + if (!categoriesExist) + { + return Result.Failure(StatusCodes.Status403Forbidden, "Category does not exist"); + } var @event = new Event { From e55616bb6daf4eff15085b04477696a3325651d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:45:23 +0200 Subject: [PATCH 03/15] Handle non existing categories --- TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs index 4360419..0f920ac 100644 --- a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs +++ b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs @@ -34,7 +34,7 @@ public async Task> GetCategoryByNameAsync(string categoryName) public async Task CheckIfCategoriesExistAsync(List categories) { var dbCategories = await _tickApiDbContext.Categories.ToListAsync(); - return categories.All(c => dbCategories.Contains(c)); + return categories.All(c => dbCategories.Any(cdb => cdb.Name == c.Name)); } public async Task AddNewCategoryAsync(Category category) From c1a6b9965f2f6449b5f5a7293381aed8aba98e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 12:46:00 +0200 Subject: [PATCH 04/15] Add ticket types to created events and tests --- .../Controllers/EventControllerTests.cs | 17 ++- .../Events/Services/EventServiceTests.cs | 123 +++++++++++++++++- .../Events/Abstractions/IEventService.cs | 3 +- .../Events/Controllers/EventController.cs | 2 +- .../Events/DTOs/Request/CreateEventDto.cs | 2 + .../TickAPI/Events/Services/EventService.cs | 31 ++++- .../Request/CreateAddressTicketTypeDto.cs | 9 ++ 7 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 TickAPI/TickAPI/TicketTypes/DTOs/Request/CreateAddressTicketTypeDto.cs diff --git a/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs b/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs index c1f2947..c0789fa 100644 --- a/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Controllers/EventControllerTests.cs @@ -14,6 +14,7 @@ using TickAPI.Events.DTOs.Response; using TickAPI.Organizers.Abstractions; using TickAPI.Organizers.Models; +using TickAPI.TicketTypes.DTOs.Request; namespace TickAPI.Tests.Events.Controllers; @@ -36,12 +37,17 @@ public async Task CreateEvent_WhenDataIsValid_ShouldReturnSuccess() new CreateEventCategoryDto("concert"), new CreateEventCategoryDto("bear metal") ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); - CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, eventStatus, createAddress); + CreateEventDto eventDto = new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress); var eventServiceMock = new Mock(); eventServiceMock - .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories ,eventStatus, email)) + .Setup(m => m.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories , ticketTypes, eventStatus, email)) .ReturnsAsync(Result.Success(new Event())); var claims = new List @@ -91,6 +97,11 @@ public async Task CreateEvent_WhenMissingEmailClaims_ShouldReturnBadRequest() new CreateEventCategoryDto("concert"), new CreateEventCategoryDto("bear metal") ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventServiceMock = new Mock(); @@ -110,7 +121,7 @@ public async Task CreateEvent_WhenMissingEmailClaims_ShouldReturnBadRequest() }; // act - var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, eventStatus, createAddress)); + var res = await sut.CreateEvent(new CreateEventDto(name, description, startDate, endDate, minimumAge, categories, ticketTypes, eventStatus, createAddress)); // Assert var result = Assert.IsType>(res); diff --git a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs index a14f429..78d2c7c 100644 --- a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs @@ -8,6 +8,7 @@ using TickAPI.Common.Pagination.Responses; using TickAPI.Categories.Abstractions; using TickAPI.Categories.DTOs.Request; +using TickAPI.Categories.Models; using TickAPI.Events.Models; using TickAPI.Organizers.Abstractions; using TickAPI.Organizers.Models; @@ -15,6 +16,8 @@ using TickAPI.Common.Time.Abstractions; using TickAPI.Events.DTOs.Response; using TickAPI.Events.Services; +using TickAPI.TicketTypes.DTOs.Request; +using TickAPI.TicketTypes.Models; namespace TickAPI.Tests.Events.Services; @@ -38,6 +41,42 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( new CreateEventCategoryDto("concert"), new CreateEventCategoryDto("bear metal") ]; + List expectedCategories = + [ + new Category + { + Name = "concert", + }, + new Category + { + Name = "bear metal", + } + + ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), + ]; + List expectedTicketTypes = + [ + new TicketType + { + Description = "normal", + MaxCount = 100, + Price = 50.9m, + Currency = "zł", + AvailableFrom = new DateTime(2025, 5, 1) + }, + new TicketType + { + Description = "V.I.P", + MaxCount = 10, + Price = 500.9m, + Currency = "zł", + AvailableFrom = new DateTime(2025, 5, 10) + }, + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -66,12 +105,13 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2003, 7, 11)); var categoryRepositoryMock = new Mock(); + categoryRepositoryMock.Setup(c => c.CheckIfCategoriesExistAsync(It.IsAny>())).Returns(Task.FromResult(true)); var paginationServiceMock = new Mock(); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); // act - var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); + var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); // Assert Assert.True(result.IsSuccess); @@ -82,6 +122,22 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( Assert.Equal(eventStatus, result.Value!.EventStatus); Assert.Equal(id, result.Value!.Id); Assert.Equal(organizerEmail, result.Value!.Organizer.Email); + Assert.Equal(expectedCategories.Count, result.Value!.Categories.Count); + foreach (var expectedCategory in expectedCategories) + { + Assert.Contains(result.Value!.Categories, actualCategory => + actualCategory.Name == expectedCategory.Name); + } + Assert.Equal(expectedTicketTypes.Count, result.Value!.TicketTypes.Count); + foreach (var expectedTicketType in expectedTicketTypes) + { + Assert.Contains(result.Value!.TicketTypes, actualTicketType => + actualTicketType.Description == expectedTicketType.Description && + actualTicketType.MaxCount == expectedTicketType.MaxCount && + actualTicketType.Price == expectedTicketType.Price && + actualTicketType.Currency == expectedTicketType.Currency && + actualTicketType.AvailableFrom == expectedTicketType.AvailableFrom); + } } [Fact] @@ -101,6 +157,11 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB new CreateEventCategoryDto("concert"), new CreateEventCategoryDto("bear metal") ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -122,7 +183,7 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); // Assert Assert.False(res.IsSuccess); @@ -130,6 +191,57 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB Assert.Equal("End date should be after start date", res.ErrorMsg); } + [Fact] + public async Task CreateNewEventAsync_WhenTicketTypeAvailabilityIsAfterEventsEnd_ShouldReturnBadRequest() + { + // Arrange + string name = "Concert"; + string description = "Description of a concert"; + DateTime startDate = new DateTime(2025, 5, 1); + DateTime endDate = new DateTime(2025, 6, 1); + uint? minimumAge = 18; + string organizerEmail = "123@mail.com"; + EventStatus eventStatus = EventStatus.TicketsAvailable; + Guid id = Guid.NewGuid(); + List categories = + [ + new CreateEventCategoryDto("concert"), + new CreateEventCategoryDto("bear metal") + ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 6, 10)), + ]; + CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); + + var eventRepositoryMock = new Mock(); + + var organizerServiceMock = new Mock(); + organizerServiceMock + .Setup(m => m.GetOrganizerByEmailAsync(organizerEmail)) + .ReturnsAsync(Result.Success(new Organizer { Email = organizerEmail, IsVerified = true })); + + var addressServiceMock = new Mock(); + + var dateTimeServiceMock = new Mock(); + dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2025, 4, 11)); + + var categoryRepositoryMock = new Mock(); + + // act + var paginationServiceMock = new Mock(); + + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); + + // Assert + Assert.False(res.IsSuccess); + Assert.Equal(StatusCodes.Status400BadRequest, res.StatusCode); + Assert.Equal("Tickets can't be available after the event is over", res.ErrorMsg); + } + [Fact] public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRequest() { @@ -147,6 +259,11 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe new CreateEventCategoryDto("concert"), new CreateEventCategoryDto("bear metal") ]; + List ticketTypes = + [ + new CreateEventTicketTypeDto("normal", 100, 50.9m, "zł", new DateTime(2025, 5, 1)), + new CreateEventTicketTypeDto("V.I.P", 10, 500.9m, "zł", new DateTime(2025, 5, 10)), + ]; CreateAddressDto createAddress = new CreateAddressDto("United States", "New York", "Main st", 20, null, "00-000"); var eventRepositoryMock = new Mock(); @@ -168,7 +285,7 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); - var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, eventStatus, organizerEmail); + var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); // Assert Assert.False(res.IsSuccess); diff --git a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs index b2267ba..465defd 100644 --- a/TickAPI/TickAPI/Events/Abstractions/IEventService.cs +++ b/TickAPI/TickAPI/Events/Abstractions/IEventService.cs @@ -5,6 +5,7 @@ using TickAPI.Common.Results.Generic; using TickAPI.Events.DTOs.Response; using TickAPI.Organizers.Models; +using TickAPI.TicketTypes.DTOs.Request; namespace TickAPI.Events.Abstractions; @@ -12,7 +13,7 @@ public interface IEventService { public Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, uint? minimumAge, CreateAddressDto createAddress, List categories - ,EventStatus eventStatus, string organizerEmail); + , List ticketTypes,EventStatus eventStatus, string organizerEmail); public Task>> GetOrganizerEventsAsync(Organizer organizer, int page, int pageSize); public Task> GetOrganizerEventsPaginationDetailsAsync(Organizer organizer, int pageSize); public Task>> GetEventsAsync(int page, int pageSize); diff --git a/TickAPI/TickAPI/Events/Controllers/EventController.cs b/TickAPI/TickAPI/Events/Controllers/EventController.cs index f368926..27594f7 100644 --- a/TickAPI/TickAPI/Events/Controllers/EventController.cs +++ b/TickAPI/TickAPI/Events/Controllers/EventController.cs @@ -40,7 +40,7 @@ public async Task> CreateEvent([FromBody] C var newEventResult = await _eventService.CreateNewEventAsync(request.Name, request.Description, request.StartDate, request.EndDate, request.MinimumAge, request.CreateAddress, request.Categories - ,request.EventStatus, email); + , request.TicketTypes ,request.EventStatus, email); if (newEventResult.IsError) return StatusCode(newEventResult.StatusCode, newEventResult.ErrorMsg); diff --git a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs index 01bb591..5b6f447 100644 --- a/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs +++ b/TickAPI/TickAPI/Events/DTOs/Request/CreateEventDto.cs @@ -1,6 +1,7 @@ using TickAPI.Events.Models; using TickAPI.Addresses.DTOs.Request; using TickAPI.Categories.DTOs.Request; +using TickAPI.TicketTypes.DTOs.Request; namespace TickAPI.Events.DTOs.Request; @@ -11,6 +12,7 @@ public record CreateEventDto( DateTime EndDate, uint? MinimumAge, List Categories, + List TicketTypes, EventStatus EventStatus, CreateAddressDto CreateAddress ); \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index 837da66..e258c92 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -12,6 +12,8 @@ using TickAPI.Events.DTOs.Response; using TickAPI.Organizers.Abstractions; using TickAPI.Organizers.Models; +using TickAPI.TicketTypes.DTOs.Request; +using TickAPI.TicketTypes.Models; namespace TickAPI.Events.Services; @@ -35,7 +37,7 @@ public EventService(IEventRepository eventRepository, IOrganizerService organize } public async Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, - uint? minimumAge, CreateAddressDto createAddress, List categories, + uint? minimumAge, CreateAddressDto createAddress, List categories, List ticketTypes, EventStatus eventStatus, string organizerEmail) { var organizerResult = await _organizerService.GetOrganizerByEmailAsync(organizerEmail); @@ -48,7 +50,14 @@ public async Task> CreateNewEventAsync(string name, string descri if (startDate < _dateTimeService.GetCurrentDateTime()) return Result.Failure(StatusCodes.Status400BadRequest, "Start date is in the past"); - + + foreach (var t in ticketTypes) + { + if (t.AvailableFrom > endDate) + { + return Result.Failure(StatusCodes.Status400BadRequest, "Tickets can't be available after the event is over"); + } + } var address = await _addressService.GetOrCreateAddressAsync(createAddress); @@ -67,6 +76,19 @@ public async Task> CreateNewEventAsync(string name, string descri { return Result.Failure(StatusCodes.Status403Forbidden, "Category does not exist"); } + + var ticketTypesConverted = new List(); + foreach (var t in ticketTypes) + { + ticketTypesConverted.Add(new TicketType + { + Description = t.Description, + AvailableFrom = t.AvailableFrom, + Currency = t.Currency, + MaxCount = t.MaxCount, + Price = t.Price, + }); + } var @event = new Event { @@ -78,7 +100,8 @@ public async Task> CreateNewEventAsync(string name, string descri Address = address.Value!, Categories = categoriesConverted, Organizer = organizerResult.Value!, - EventStatus = eventStatus + EventStatus = eventStatus, + TicketTypes = ticketTypesConverted, }; await _eventRepository.AddNewEventAsync(@event); return Result.Success(@event); @@ -123,7 +146,7 @@ private async Task>> GetPaginatedEvent private static GetEventResponseDto MapEventToGetEventResponseDto(Event ev) { - var categories = ev.Categories.Select((c) => new GetEventResponseCategoryDto(c.Name)).ToList(); + var categories = ev.Categories.Count > 0 ? ev.Categories.Select((c) => new GetEventResponseCategoryDto(c.Name)).ToList() : new List(); var address = new GetEventResponseAddressDto(ev.Address.Country, ev.Address.City, ev.Address.PostalCode, ev.Address.Street, ev.Address.HouseNumber, ev.Address.FlatNumber); return new GetEventResponseDto(ev.Name, ev.Description, ev.StartDate, ev.EndDate, ev.MinimumAge, categories, ev.EventStatus, address); } diff --git a/TickAPI/TickAPI/TicketTypes/DTOs/Request/CreateAddressTicketTypeDto.cs b/TickAPI/TickAPI/TicketTypes/DTOs/Request/CreateAddressTicketTypeDto.cs new file mode 100644 index 0000000..96a002c --- /dev/null +++ b/TickAPI/TickAPI/TicketTypes/DTOs/Request/CreateAddressTicketTypeDto.cs @@ -0,0 +1,9 @@ +namespace TickAPI.TicketTypes.DTOs.Request; + +public record CreateEventTicketTypeDto( + string Description, + uint MaxCount, + decimal Price, + string Currency, + DateTime AvailableFrom + ); \ No newline at end of file From c6e4cd64d91d77f95e0697a596e78cd6ee223478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:46:49 +0200 Subject: [PATCH 05/15] Add or update the Azure App Service build and deployment workflow config --- ...twithcategoriesandtickettyped_resellio.yml | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml new file mode 100644 index 0000000..7376649 --- /dev/null +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -0,0 +1,68 @@ +# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy +# More GitHub Actions for Azure: https://github.com/Azure/actions + +name: Build and deploy ASP.Net Core app to Azure Web App - resellio + +on: + push: + branches: + - feat/CreateEventWithCategoriesAndTicketTyped + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + permissions: + contents: read #This is required for actions/checkout + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '6.0.x' + + - name: Build with dotnet + run: dotnet build --configuration Release + + - name: dotnet publish + run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/myapp" + + - name: Upload artifact for deployment job + uses: actions/upload-artifact@v4 + with: + name: .net-app + path: ${{env.DOTNET_ROOT}}/myapp + + deploy: + runs-on: windows-latest + needs: build + environment: + name: 'Production' + url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + permissions: + id-token: write #This is required for requesting the JWT + contents: read #This is required for actions/checkout + + steps: + - name: Download artifact from build job + uses: actions/download-artifact@v4 + with: + name: .net-app + + - name: Login to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_0D0336DEAF734574B53DD4A5D2E898A0 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_800D316A4C714278AB484F215A6303F0 }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_E2CF62C6C3CB48B0AFF01965324F5D3A }} + + - name: Deploy to Azure Web App + id: deploy-to-webapp + uses: azure/webapps-deploy@v3 + with: + app-name: 'resellio' + slot-name: 'Production' + package: . + \ No newline at end of file From 49cf8dd456d9079dd152cb6606e3b79dc734015a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:53:34 +0200 Subject: [PATCH 06/15] Add or update the Azure App Service build and deployment workflow config --- ...eat-createeventwithcategoriesandtickettyped_resellio.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index 7376649..39af33e 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -54,9 +54,9 @@ jobs: - name: Login to Azure uses: azure/login@v2 with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_0D0336DEAF734574B53DD4A5D2E898A0 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_800D316A4C714278AB484F215A6303F0 }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_E2CF62C6C3CB48B0AFF01965324F5D3A }} + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_1E79017744574753935FA54217321744 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_45CB50561E614FBB9482DD79882CEA2A }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_036603283F034371B4B2C33640B40CEB }} - name: Deploy to Azure Web App id: deploy-to-webapp From 15ae96aa337b5559e6aebd4e16e527161cfb902d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:57:56 +0200 Subject: [PATCH 07/15] Update feat-createeventwithcategoriesandtickettyped_resellio.yml --- ...twithcategoriesandtickettyped_resellio.yml | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index 39af33e..f54eca3 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -27,36 +27,36 @@ jobs: run: dotnet build --configuration Release - name: dotnet publish - run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/myapp" + run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/TickApi" - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: .net-app - path: ${{env.DOTNET_ROOT}}/myapp + path: ${{env.DOTNET_ROOT}}/TickApi deploy: runs-on: windows-latest needs: build - environment: - name: 'Production' + environment: + name: 'Production' url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout + permissions: + id-token: write #This is required for requesting the JWT + contents: read #This is required for actions/checkout steps: - name: Download artifact from build job uses: actions/download-artifact@v4 with: name: .net-app - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_1E79017744574753935FA54217321744 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_45CB50561E614FBB9482DD79882CEA2A }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_036603283F034371B4B2C33640B40CEB }} + + - name: Login to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_1E79017744574753935FA54217321744 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_45CB50561E614FBB9482DD79882CEA2A }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_036603283F034371B4B2C33640B40CEB }} - name: Deploy to Azure Web App id: deploy-to-webapp @@ -65,4 +65,4 @@ jobs: app-name: 'resellio' slot-name: 'Production' package: . - \ No newline at end of file + From 27ed684bd944b9851aa2589ee0191a55a7d2fb57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:00:08 +0200 Subject: [PATCH 08/15] Update feat-createeventwithcategoriesandtickettyped_resellio.yml --- .../feat-createeventwithcategoriesandtickettyped_resellio.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index f54eca3..d46be99 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -27,13 +27,13 @@ jobs: run: dotnet build --configuration Release - name: dotnet publish - run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/TickApi" + run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/TickAPI/TickAPI.sln" - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: .net-app - path: ${{env.DOTNET_ROOT}}/TickApi + path: ${{env.DOTNET_ROOT}}/TickAPI/TickAPI.sln deploy: runs-on: windows-latest From ea3546a3e172a577faac43530df310cf69b885a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:04:46 +0200 Subject: [PATCH 09/15] Update feat-createeventwithcategoriesandtickettyped_resellio.yml --- ...twithcategoriesandtickettyped_resellio.yml | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index d46be99..bec4fa9 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -1,40 +1,36 @@ # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy # More GitHub Actions for Azure: https://github.com/Azure/actions - name: Build and deploy ASP.Net Core app to Azure Web App - resellio - on: push: branches: - feat/CreateEventWithCategoriesAndTicketTyped workflow_dispatch: - jobs: build: runs-on: windows-latest permissions: contents: read #This is required for actions/checkout - steps: - uses: actions/checkout@v4 - + - name: Set up .NET Core uses: actions/setup-dotnet@v4 with: dotnet-version: '6.0.x' - + - name: Build with dotnet - run: dotnet build --configuration Release - + run: dotnet build TickAPI/TickAPI.sln --configuration Release + - name: dotnet publish - run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/TickAPI/TickAPI.sln" - + run: dotnet publish TickAPI/TickAPI.sln -c Release -o "${{env.DOTNET_ROOT}}/myapp" + - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: .net-app - path: ${{env.DOTNET_ROOT}}/TickAPI/TickAPI.sln - + path: ${{env.DOTNET_ROOT}}/myapp + deploy: runs-on: windows-latest needs: build @@ -44,7 +40,6 @@ jobs: permissions: id-token: write #This is required for requesting the JWT contents: read #This is required for actions/checkout - steps: - name: Download artifact from build job uses: actions/download-artifact@v4 @@ -54,10 +49,10 @@ jobs: - name: Login to Azure uses: azure/login@v2 with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_1E79017744574753935FA54217321744 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_45CB50561E614FBB9482DD79882CEA2A }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_036603283F034371B4B2C33640B40CEB }} - + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_0D0336DEAF734574B53DD4A5D2E898A0 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_800D316A4C714278AB484F215A6303F0 }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_E2CF62C6C3CB48B0AFF01965324F5D3A }} + - name: Deploy to Azure Web App id: deploy-to-webapp uses: azure/webapps-deploy@v3 @@ -65,4 +60,3 @@ jobs: app-name: 'resellio' slot-name: 'Production' package: . - From bc1ba00ac946c6d15d46110376c6b79114bf7c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:17:43 +0200 Subject: [PATCH 10/15] Update feat-createeventwithcategoriesandtickettyped_resellio.yml --- .../feat-createeventwithcategoriesandtickettyped_resellio.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index bec4fa9..fc03c07 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -20,10 +20,10 @@ jobs: dotnet-version: '6.0.x' - name: Build with dotnet - run: dotnet build TickAPI/TickAPI.sln --configuration Release + run: dotnet build TickAPI/TickAPI/TickAPI.csproj --configuration Release - name: dotnet publish - run: dotnet publish TickAPI/TickAPI.sln -c Release -o "${{env.DOTNET_ROOT}}/myapp" + run: dotnet publish TickAPI/TickAPI/TickAPI.csproj -c Release -o "${{env.DOTNET_ROOT}}/myapp" - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 From 125d691b181c9c5eec2d89026de8d16826fe24f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:24:52 +0200 Subject: [PATCH 11/15] Delete .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml --- ...twithcategoriesandtickettyped_resellio.yml | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml deleted file mode 100644 index fc03c07..0000000 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ /dev/null @@ -1,62 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy -# More GitHub Actions for Azure: https://github.com/Azure/actions -name: Build and deploy ASP.Net Core app to Azure Web App - resellio -on: - push: - branches: - - feat/CreateEventWithCategoriesAndTicketTyped - workflow_dispatch: -jobs: - build: - runs-on: windows-latest - permissions: - contents: read #This is required for actions/checkout - steps: - - uses: actions/checkout@v4 - - - name: Set up .NET Core - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '6.0.x' - - - name: Build with dotnet - run: dotnet build TickAPI/TickAPI/TickAPI.csproj --configuration Release - - - name: dotnet publish - run: dotnet publish TickAPI/TickAPI/TickAPI.csproj -c Release -o "${{env.DOTNET_ROOT}}/myapp" - - - name: Upload artifact for deployment job - uses: actions/upload-artifact@v4 - with: - name: .net-app - path: ${{env.DOTNET_ROOT}}/myapp - - deploy: - runs-on: windows-latest - needs: build - environment: - name: 'Production' - url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout - steps: - - name: Download artifact from build job - uses: actions/download-artifact@v4 - with: - name: .net-app - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_0D0336DEAF734574B53DD4A5D2E898A0 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_800D316A4C714278AB484F215A6303F0 }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_E2CF62C6C3CB48B0AFF01965324F5D3A }} - - - name: Deploy to Azure Web App - id: deploy-to-webapp - uses: azure/webapps-deploy@v3 - with: - app-name: 'resellio' - slot-name: 'Production' - package: . From 8fa7d7e9f62eca0df8060d05029275e8d36f5d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:34:57 +0200 Subject: [PATCH 12/15] Add or update the Azure App Service build and deployment workflow config --- ...twithcategoriesandtickettyped_resellio.yml | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml new file mode 100644 index 0000000..5dc9ed9 --- /dev/null +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -0,0 +1,68 @@ +# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy +# More GitHub Actions for Azure: https://github.com/Azure/actions + +name: Build and deploy ASP.Net Core app to Azure Web App - resellio + +on: + push: + branches: + - feat/CreateEventWithCategoriesAndTicketTyped + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + permissions: + contents: read #This is required for actions/checkout + + steps: + - uses: actions/checkout@v4 + + - name: Set up .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.x' + + - name: Build with dotnet + run: dotnet build --configuration Release + + - name: dotnet publish + run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/myapp" + + - name: Upload artifact for deployment job + uses: actions/upload-artifact@v4 + with: + name: .net-app + path: ${{env.DOTNET_ROOT}}/myapp + + deploy: + runs-on: windows-latest + needs: build + environment: + name: 'Production' + url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} + permissions: + id-token: write #This is required for requesting the JWT + contents: read #This is required for actions/checkout + + steps: + - name: Download artifact from build job + uses: actions/download-artifact@v4 + with: + name: .net-app + + - name: Login to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_F22C931708554F8B83EE4F83C4FED407 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_6CDAC678ACD94858BF3421F606456B8B }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_CA368EC8EA37446E96D5DF5F42B650EA }} + + - name: Deploy to Azure Web App + id: deploy-to-webapp + uses: azure/webapps-deploy@v3 + with: + app-name: 'resellio' + slot-name: 'Production' + package: . + \ No newline at end of file From 18b9dc022ca202109c026ba842b3817fabf54a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:36:35 +0200 Subject: [PATCH 13/15] Update feat-createeventwithcategoriesandtickettyped_resellio.yml --- ...twithcategoriesandtickettyped_resellio.yml | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml index 5dc9ed9..5971dad 100644 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml @@ -24,10 +24,10 @@ jobs: dotnet-version: '9.x' - name: Build with dotnet - run: dotnet build --configuration Release + run: dotnet build TIckAPI/TickAPI.sln --configuration Release - name: dotnet publish - run: dotnet publish -c Release -o "${{env.DOTNET_ROOT}}/myapp" + run: dotnet publish TIckAPI/TickAPI.sln -c Release -o "${{env.DOTNET_ROOT}}/myapp" - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 @@ -38,25 +38,25 @@ jobs: deploy: runs-on: windows-latest needs: build - environment: - name: 'Production' + environment: + name: 'Production' url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout + permissions: + id-token: write #This is required for requesting the JWT + contents: read #This is required for actions/checkout steps: - name: Download artifact from build job uses: actions/download-artifact@v4 with: name: .net-app - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_F22C931708554F8B83EE4F83C4FED407 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_6CDAC678ACD94858BF3421F606456B8B }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_CA368EC8EA37446E96D5DF5F42B650EA }} + + - name: Login to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_F22C931708554F8B83EE4F83C4FED407 }} + tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_6CDAC678ACD94858BF3421F606456B8B }} + subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_CA368EC8EA37446E96D5DF5F42B650EA }} - name: Deploy to Azure Web App id: deploy-to-webapp @@ -65,4 +65,4 @@ jobs: app-name: 'resellio' slot-name: 'Production' package: . - \ No newline at end of file + From 23087d1cb8501b72a393b3e52ea43aaf1ac6a618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:44:41 +0200 Subject: [PATCH 14/15] Delete .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml --- ...twithcategoriesandtickettyped_resellio.yml | 68 ------------------- 1 file changed, 68 deletions(-) delete mode 100644 .github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml diff --git a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml b/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml deleted file mode 100644 index 5971dad..0000000 --- a/.github/workflows/feat-createeventwithcategoriesandtickettyped_resellio.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy -# More GitHub Actions for Azure: https://github.com/Azure/actions - -name: Build and deploy ASP.Net Core app to Azure Web App - resellio - -on: - push: - branches: - - feat/CreateEventWithCategoriesAndTicketTyped - workflow_dispatch: - -jobs: - build: - runs-on: windows-latest - permissions: - contents: read #This is required for actions/checkout - - steps: - - uses: actions/checkout@v4 - - - name: Set up .NET Core - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '9.x' - - - name: Build with dotnet - run: dotnet build TIckAPI/TickAPI.sln --configuration Release - - - name: dotnet publish - run: dotnet publish TIckAPI/TickAPI.sln -c Release -o "${{env.DOTNET_ROOT}}/myapp" - - - name: Upload artifact for deployment job - uses: actions/upload-artifact@v4 - with: - name: .net-app - path: ${{env.DOTNET_ROOT}}/myapp - - deploy: - runs-on: windows-latest - needs: build - environment: - name: 'Production' - url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - permissions: - id-token: write #This is required for requesting the JWT - contents: read #This is required for actions/checkout - - steps: - - name: Download artifact from build job - uses: actions/download-artifact@v4 - with: - name: .net-app - - - name: Login to Azure - uses: azure/login@v2 - with: - client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_F22C931708554F8B83EE4F83C4FED407 }} - tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_6CDAC678ACD94858BF3421F606456B8B }} - subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_CA368EC8EA37446E96D5DF5F42B650EA }} - - - name: Deploy to Azure Web App - id: deploy-to-webapp - uses: azure/webapps-deploy@v3 - with: - app-name: 'resellio' - slot-name: 'Production' - package: . - From 7ab354772143500688c27bb964c87a7be472a276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= <62651497+staszkiet@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:56:36 +0200 Subject: [PATCH 15/15] Resolve comments --- .../Events/Services/EventServiceTests.cs | 50 +++++++++---------- .../Abstractions/ICategoryRepository.cs | 2 - .../Abstractions/ICategoryService.cs | 2 + .../Respositories/CategoryRepository.cs | 6 --- .../Categories/Services/CategoryService.cs | 10 +++- .../TickAPI/Events/Services/EventService.cs | 38 +++++--------- 6 files changed, 48 insertions(+), 60 deletions(-) diff --git a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs index 78d2c7c..0989a18 100644 --- a/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs +++ b/TickAPI/TickAPI.Tests/Events/Services/EventServiceTests.cs @@ -104,13 +104,13 @@ public async Task CreateNewEventAsync_WhenEventDataIsValid_ShouldReturnNewEvent( var dateTimeServiceMock = new Mock(); dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2003, 7, 11)); - var categoryRepositoryMock = new Mock(); - categoryRepositoryMock.Setup(c => c.CheckIfCategoriesExistAsync(It.IsAny>())).Returns(Task.FromResult(true)); + var categoryServiceMock = new Mock(); + categoryServiceMock.Setup(c => c.CheckIfCategoriesExistAsync(It.IsAny>())).Returns(Task.FromResult(true)); var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); - // act + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); + // Act var result = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); // Assert @@ -175,13 +175,13 @@ public async Task CreateNewEventAsync_WhenEndDateIsBeforeStartDate_ShouldReturnB var dateTimeServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); - // act + // Act var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); @@ -227,12 +227,12 @@ public async Task CreateNewEventAsync_WhenTicketTypeAvailabilityIsAfterEventsEnd var dateTimeServiceMock = new Mock(); dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2025, 4, 11)); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); - // act + // Act var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); @@ -278,12 +278,12 @@ public async Task CreateNewEventAsync_WhenStartDateIsBeforeNow_ShouldReturnBadRe var dateTimeServiceMock = new Mock(); dateTimeServiceMock.Setup(m => m.GetCurrentDateTime()).Returns(new DateTime(2025, 5, 11)); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); - // act + // Act var paginationServiceMock = new Mock(); - var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); var res = await sut.CreateNewEventAsync(name, description, startDate, endDate, minimumAge, createAddress, categories, ticketTypes, eventStatus, organizerEmail); @@ -316,7 +316,7 @@ public async Task GetOrganizerEvents_WhenPaginationSucceeds_ShouldReturnPaginate var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var paginatedEvents = new PaginatedData( organizer.Events.Take(pageSize).ToList(), @@ -350,7 +350,7 @@ public async Task GetOrganizerEvents_WhenPaginationSucceeds_ShouldReturnPaginate )); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -390,7 +390,7 @@ public async Task GetOrganizerEvents_WhenPaginationFails_ShouldPropagateError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var organizerEvents = organizer.Events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEventsByOranizer(organizer)).Returns(organizerEvents); @@ -400,7 +400,7 @@ public async Task GetOrganizerEvents_WhenPaginationFails_ShouldPropagateError() .ReturnsAsync(Result>.Failure(StatusCodes.Status400BadRequest, "Invalid page number")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetOrganizerEventsAsync(organizer, page, pageSize); @@ -429,7 +429,7 @@ public async Task GetEventsAsync_WhenPaginationSucceeds_ShouldReturnPaginatedEve var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var paginatedEvents = new PaginatedData( events.Take(pageSize).ToList(), @@ -463,7 +463,7 @@ public async Task GetEventsAsync_WhenPaginationSucceeds_ShouldReturnPaginatedEve )); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -498,7 +498,7 @@ public async Task GetEventsAsync_WhenPaginationFails_ShouldPropagateError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -508,7 +508,7 @@ public async Task GetEventsAsync_WhenPaginationFails_ShouldPropagateError() .ReturnsAsync(Result>.Failure(StatusCodes.Status400BadRequest, "Invalid page number")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetEventsAsync(page, pageSize); @@ -536,7 +536,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenSuccessful_ShouldReturnPag var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -547,7 +547,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenSuccessful_ShouldReturnPag .ReturnsAsync(Result.Success(paginationDetails)); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); @@ -574,7 +574,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenFails_ShouldReturnError() var addressServiceMock = new Mock(); var dateTimeServiceMock = new Mock(); var paginationServiceMock = new Mock(); - var categoryRepositoryMock = new Mock(); + var categoryServiceMock = new Mock(); var eventsQueryable = events.AsQueryable(); eventRepositoryMock.Setup(p => p.GetEvents()).Returns(eventsQueryable); @@ -584,7 +584,7 @@ public async Task GetEventsPaginationDetailsAsync_WhenFails_ShouldReturnError() .ReturnsAsync(Result.Failure(StatusCodes.Status400BadRequest, "Invalid page size")); var sut = new EventService(eventRepositoryMock.Object, organizerServiceMock.Object, addressServiceMock.Object, - dateTimeServiceMock.Object, paginationServiceMock.Object, categoryRepositoryMock.Object); + dateTimeServiceMock.Object, paginationServiceMock.Object, categoryServiceMock.Object); // Act var result = await sut.GetEventsPaginationDetailsAsync(pageSize); diff --git a/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs b/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs index 9e6e598..c7d1fc3 100644 --- a/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs +++ b/TickAPI/TickAPI/Categories/Abstractions/ICategoryRepository.cs @@ -8,6 +8,4 @@ public interface ICategoryRepository public IQueryable GetCategories(); public Task> GetCategoryByNameAsync(string categoryName); public Task AddNewCategoryAsync(Category category); - - public Task CheckIfCategoriesExistAsync(List categories); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Categories/Abstractions/ICategoryService.cs b/TickAPI/TickAPI/Categories/Abstractions/ICategoryService.cs index 0e33bf0..8560738 100644 --- a/TickAPI/TickAPI/Categories/Abstractions/ICategoryService.cs +++ b/TickAPI/TickAPI/Categories/Abstractions/ICategoryService.cs @@ -10,4 +10,6 @@ public interface ICategoryService public Task> GetCategoryByNameAsync(string categoryName); public Task>> GetCategoriesResponsesAsync(int pageSize, int page); public Task> CreateNewCategoryAsync(string categoryName); + + public Task CheckIfCategoriesExistAsync(IEnumerable categories); } \ No newline at end of file diff --git a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs index 0f920ac..e1dcdb2 100644 --- a/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs +++ b/TickAPI/TickAPI/Categories/Respositories/CategoryRepository.cs @@ -31,12 +31,6 @@ public async Task> GetCategoryByNameAsync(string categoryName) return Result.Success(category); } - public async Task CheckIfCategoriesExistAsync(List categories) - { - var dbCategories = await _tickApiDbContext.Categories.ToListAsync(); - return categories.All(c => dbCategories.Any(cdb => cdb.Name == c.Name)); - } - public async Task AddNewCategoryAsync(Category category) { _tickApiDbContext.Categories.Add(category); diff --git a/TickAPI/TickAPI/Categories/Services/CategoryService.cs b/TickAPI/TickAPI/Categories/Services/CategoryService.cs index 929c99e..e30dafc 100644 --- a/TickAPI/TickAPI/Categories/Services/CategoryService.cs +++ b/TickAPI/TickAPI/Categories/Services/CategoryService.cs @@ -1,4 +1,5 @@ -using TickAPI.Categories.Abstractions; +using Microsoft.EntityFrameworkCore; +using TickAPI.Categories.Abstractions; using TickAPI.Categories.DTOs.Response; using TickAPI.Categories.Models; using TickAPI.Common.Pagination.Abstractions; @@ -55,4 +56,11 @@ public async Task> CreateNewCategoryAsync(string categoryName) await _categoryRepository.AddNewCategoryAsync(category); return Result.Success(category); } + + public async Task CheckIfCategoriesExistAsync(IEnumerable categories) + { + var dbCategories = _categoryRepository.GetCategories(); + int count = await dbCategories.Where(cdb => categories.Any(c => c.Name == cdb.Name)).CountAsync(); + return count == categories.Count(); + } } \ No newline at end of file diff --git a/TickAPI/TickAPI/Events/Services/EventService.cs b/TickAPI/TickAPI/Events/Services/EventService.cs index e258c92..117c7eb 100644 --- a/TickAPI/TickAPI/Events/Services/EventService.cs +++ b/TickAPI/TickAPI/Events/Services/EventService.cs @@ -24,16 +24,16 @@ public class EventService : IEventService private readonly IAddressService _addressService; private readonly IDateTimeService _dateTimeService; private readonly IPaginationService _paginationService; - private readonly ICategoryRepository _categoryRepository; + private readonly ICategoryService _categoryService; - public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryRepository categoryRepository) + public EventService(IEventRepository eventRepository, IOrganizerService organizerService, IAddressService addressService, IDateTimeService dateTimeService, IPaginationService paginationService, ICategoryService categoryService) { _eventRepository = eventRepository; _organizerService = organizerService; _addressService = addressService; _dateTimeService = dateTimeService; _paginationService = paginationService; - _categoryRepository = categoryRepository; + _categoryService = categoryService; } public async Task> CreateNewEventAsync(string name, string description, DateTime startDate, DateTime endDate, @@ -51,45 +51,31 @@ public async Task> CreateNewEventAsync(string name, string descri if (startDate < _dateTimeService.GetCurrentDateTime()) return Result.Failure(StatusCodes.Status400BadRequest, "Start date is in the past"); - foreach (var t in ticketTypes) + if (ticketTypes.Any(t => t.AvailableFrom > endDate)) { - if (t.AvailableFrom > endDate) - { - return Result.Failure(StatusCodes.Status400BadRequest, "Tickets can't be available after the event is over"); - } + return Result.Failure(StatusCodes.Status400BadRequest, "Tickets can't be available after the event is over"); } var address = await _addressService.GetOrCreateAddressAsync(createAddress); - var categoriesConverted = new List(); - - foreach (var c in categories) - { - categoriesConverted.Add(new Category - { - Name = c.CategoryName - }); - } + var categoriesConverted = categories.Select(c => new Category { Name = c.CategoryName }).ToList(); - var categoriesExist = await _categoryRepository.CheckIfCategoriesExistAsync(categoriesConverted); + var categoriesExist = await _categoryService.CheckIfCategoriesExistAsync(categoriesConverted); if (!categoriesExist) { - return Result.Failure(StatusCodes.Status403Forbidden, "Category does not exist"); + return Result.Failure(StatusCodes.Status400BadRequest, "Category does not exist"); } - var ticketTypesConverted = new List(); - foreach (var t in ticketTypes) - { - ticketTypesConverted.Add(new TicketType + var ticketTypesConverted = ticketTypes.Select(t => new TicketType { Description = t.Description, AvailableFrom = t.AvailableFrom, Currency = t.Currency, MaxCount = t.MaxCount, Price = t.Price, - }); - } - + }) + .ToList(); + var @event = new Event { Name = name,