diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/AddressInfoDto.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/AddressInfoDto.cs index a48b016a8..063c2e6ab 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/AddressInfoDto.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/AddressInfoDto.cs @@ -1,14 +1,10 @@ -using System.ComponentModel.DataAnnotations; - -namespace OutOfSchool.BusinessLogic.Models.Exported; +namespace OutOfSchool.BusinessLogic.Models.Exported; public class AddressInfoDto { - public long Id { get; set; } - public string Street { get; set; } = string.Empty; public string BuildingNumber { get; set; } = string.Empty; - public CodeficatorAddressInfoDto CodeficatorAddressDto { get; set; } + public CodeficatorAddressInfoDto CodeficatorAddress { get; set; } } diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/CodeficatorAddressInfoDto.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/CodeficatorAddressInfoDto.cs index 0bdcab357..391ce1e4c 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/CodeficatorAddressInfoDto.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/CodeficatorAddressInfoDto.cs @@ -2,8 +2,6 @@ public class CodeficatorAddressInfoDto { - public int Id { get; set; } - public string Region { get; set; } public string District { get; set; } @@ -13,4 +11,6 @@ public class CodeficatorAddressInfoDto public string Settlement { get; set; } public string CityDistrict { get; set; } + + public string Code { get; set; } } diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/ProviderInfoDto.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/ProviderInfoDto.cs index e18de504f..b595f2746 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/ProviderInfoDto.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/ProviderInfoDto.cs @@ -70,7 +70,7 @@ public class ProviderInfoDto : ProviderInfoBaseDto, IExternalRatingInfo [MaxLength(Constants.MaxProviderFounderLength)] public string Founder { get; set; } = string.Empty; - public ProviderTypeDto Type { get; set; } + public string Type { get; set; } [Required] [EnumDataType(typeof(ProviderStatus), ErrorMessage = Constants.EnumErrorMessage)] @@ -91,7 +91,7 @@ public class ProviderInfoDto : ProviderInfoBaseDto, IExternalRatingInfo public AddressInfoDto ActualAddress { get; set; } - public InstitutionDto Institution { get; set; } + public string Institution { get; set; } [Required] [EnumDataType(typeof(InstitutionType), ErrorMessage = Constants.EnumErrorMessage)] diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/WorkshopInfoDto.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/WorkshopInfoDto.cs index ce1f5dabf..52ddd589e 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/WorkshopInfoDto.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Models/Exported/WorkshopInfoDto.cs @@ -12,7 +12,7 @@ public class WorkshopInfoDto : WorkshopInfoBaseDto, IExternalRatingInfo public Guid? ParentWorkshopId { get; set; } - public uint TakenSeats { get; set; } = 0; + public int TakenSeats { get; set; } = 0; public float Rating { get; set; } diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Services/ExternalExportService.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Services/ExternalExportService.cs index 44c3f9a81..3007bd34e 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Services/ExternalExportService.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Services/ExternalExportService.cs @@ -1,4 +1,5 @@ -using AutoMapper; +using System.Linq.Expressions; +using AutoMapper; using OutOfSchool.BusinessLogic.Models; using OutOfSchool.BusinessLogic.Models.Exported; using OutOfSchool.BusinessLogic.Services.AverageRatings; @@ -8,8 +9,15 @@ namespace OutOfSchool.BusinessLogic.Services; public class ExternalExportService : IExternalExportService { + private const string ProviderIncludes = + "ProviderSectionItems,Images,Institution,ActualAddress,ActualAddress.CATOTTG.Parent.Parent.Parent.Parent,LegalAddress,LegalAddress.CATOTTG.Parent.Parent.Parent.Parent,Type"; + + private const string WorkshopIncludes = + "WorkshopDescriptionItems,Tags,Address,Address.CATOTTG.Parent.Parent.Parent.Parent,Images,DateTimeRanges,Teachers,InstitutionHierarchy,InstitutionHierarchy.Institution,InstitutionHierarchy.Directions,DefaultTeacher"; + private readonly IProviderRepository providerRepository; private readonly IWorkshopRepository workshopRepository; + private readonly IApplicationRepository applicationRepository; private readonly IAverageRatingService averageRatingService; private readonly IMapper mapper; private readonly ILogger logger; @@ -17,12 +25,15 @@ public class ExternalExportService : IExternalExportService public ExternalExportService( IProviderRepository providerRepository, IWorkshopRepository workshopRepository, + IApplicationRepository applicationRepository, IAverageRatingService averageRatingService, IMapper mapper, ILogger logger) { this.providerRepository = providerRepository ?? throw new ArgumentNullException(nameof(providerRepository)); this.workshopRepository = workshopRepository ?? throw new ArgumentNullException(nameof(workshopRepository)); + this.applicationRepository = + applicationRepository ?? throw new ArgumentNullException(nameof(applicationRepository)); this.averageRatingService = averageRatingService ?? throw new ArgumentNullException(nameof(averageRatingService)); this.mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); @@ -34,17 +45,21 @@ public async Task> GetProviders(DateTime updat { try { - logger.LogInformation("Getting all updated providers started"); + logger.LogDebug("Getting all updated providers started"); offsetFilter ??= new OffsetFilter(); - var providers = await providerRepository - .GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size) - .ConfigureAwait(false); - if (providers == null) - { - logger.LogError("Failed to retrieve updated providers. The provider list is null"); - return new SearchResult(); - } + Expression> filterExpression = updatedAfter == default + ? provider => !provider.IsDeleted + : provider => provider.UpdatedAt > updatedAfter || + provider.Workshops.Any(w => w.UpdatedAt > updatedAfter); + + var providers = await providerRepository.Get( + offsetFilter.From, + offsetFilter.Size, + ProviderIncludes, + filterExpression) + .ToListAsync() + .ConfigureAwait(false); var providersDto = providers .Select(MapToInfoProviderDto) @@ -52,7 +67,7 @@ public async Task> GetProviders(DateTime updat await FillRatingsForType(providersDto).ConfigureAwait(false); - var count = await providerRepository.CountWithDeleted(updatedAfter); + var count = await providerRepository.Count(filterExpression); var searchResult = new SearchResult { @@ -65,7 +80,7 @@ public async Task> GetProviders(DateTime updat catch (Exception ex) { logger.LogError(ex, "An unexpected error occurred while processing providers"); - return new SearchResult(); + throw; } } @@ -73,24 +88,27 @@ public async Task> GetWorkshops(DateTime updat { try { - logger.LogInformation("Getting all updated providers started"); + logger.LogDebug("Getting all updated providers started"); offsetFilter ??= new OffsetFilter(); - var workshops = await workshopRepository - .GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size) - .ConfigureAwait(false); + Expression> filterExpression = updatedAfter == default + ? workshop => !workshop.IsDeleted + : workshop => workshop.UpdatedAt > updatedAfter || workshop.DeleteDate > updatedAfter; - if (workshops == null) - { - logger.LogError("Failed to retrieve updated workshops. The workshop list is null"); - return new SearchResult(); - } + var workshops = await workshopRepository.Get( + offsetFilter.From, + offsetFilter.Size, + WorkshopIncludes, + filterExpression) + .ToListAsync() + .ConfigureAwait(false); var workshopsDto = workshops.Select(MapToInfoWorkshopDto).ToList(); - await FillRatingsForType(workshopsDto); + await FillRatingsForType(workshopsDto).ConfigureAwait(false); + await FillTakenSeats(workshopsDto).ConfigureAwait(false); - var count = await workshopRepository.CountWithDeleted(updatedAfter); + var count = await workshopRepository.Count(filterExpression).ConfigureAwait(false); return new SearchResult { @@ -101,7 +119,7 @@ public async Task> GetWorkshops(DateTime updat catch (Exception ex) { logger.LogError(ex, "An unexpected error occurred while processing workshops"); - return new SearchResult(); + throw; } } @@ -134,4 +152,16 @@ private async Task FillRatingsForType(List dtos) dto.NumberOfRatings = averageRatingsForProvider?.RateQuantity ?? 0; } } + + private async Task FillTakenSeats(List dtos) + { + var fullDtos = dtos.OfType().ToList(); + var ids = fullDtos.Select(w => w.Id).ToList(); + var takenSeats = await applicationRepository.CountTakenSeatsForWorkshops(ids).ConfigureAwait(false); + foreach (var dto in fullDtos) + { + var takenSeat = takenSeats?.SingleOrDefault(w => w.WorkshopId == dto.Id)?.TakenSeats; + dto.TakenSeats = takenSeat ?? 0; + } + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.BusinessLogic/Util/MappingProfile.cs b/OutOfSchool/OutOfSchool.BusinessLogic/Util/MappingProfile.cs index a78c850d5..bfdd061ef 100644 --- a/OutOfSchool/OutOfSchool.BusinessLogic/Util/MappingProfile.cs +++ b/OutOfSchool/OutOfSchool.BusinessLogic/Util/MappingProfile.cs @@ -233,7 +233,7 @@ public MappingProfile() .ForMember(dest => dest.CodeficatorAddressDto, opt => opt.MapFrom(src => src.CATOTTG)); CreateMap() - .ForMember(dest => dest.CodeficatorAddressDto, opt => opt.MapFrom(src => src.CATOTTG)); + .ForMember(dest => dest.CodeficatorAddress, opt => opt.MapFrom(src => src.CATOTTG)); /// /// The localization is done outside the mapping @@ -391,7 +391,7 @@ public MappingProfile() opt => opt.MapFrom(src => src.WorkshopDescriptionItems.Where(x => !x.IsDeleted))) .ForMember(dest => dest.Price, opt => opt.MapFrom(src => src.Price)) .ForMember(dest => dest.PayRate, opt => opt.MapFrom(src => src.PayRate)) - .ForMember(dest => dest.TakenSeats, opt => opt.MapFrom(src => src.Applications.TakenSeats())) + .ForMember(dest => dest.TakenSeats, opt => opt.Ignore()) .ForMember(dest => dest.ImageIds, opt => opt.MapFrom(src => src.Images.Select(x => x.ExternalStorageId))) .ForMember(dest => dest.Tags, opt => opt.MapFrom(src => src.Tags.Select(x => x.Name))) .ForMember(dest => dest.LanguageOfEducation, opt => opt.Ignore()) @@ -402,6 +402,8 @@ public MappingProfile() CreateMap() .IncludeBase() + .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src.Type.Name)) + .ForMember(dest => dest.Institution, opt => opt.MapFrom(src => src.Institution.Title)) .ForMember(dest => dest.ImageIds, opt => opt.MapFrom(src => src.Images.Select(x => x.ExternalStorageId))) .ForMember(dest => dest.Rating, opt => opt.Ignore()) .ForMember(dest => dest.NumberOfRatings, opt => opt.Ignore()); diff --git a/OutOfSchool/OutOfSchool.Common/Enums/Workshop/WorkshopType.cs b/OutOfSchool/OutOfSchool.Common/Enums/Workshop/WorkshopType.cs index 5c6170268..663bee234 100644 --- a/OutOfSchool/OutOfSchool.Common/Enums/Workshop/WorkshopType.cs +++ b/OutOfSchool/OutOfSchool.Common/Enums/Workshop/WorkshopType.cs @@ -2,6 +2,7 @@ namespace OutOfSchool.Common.Enums.Workshop; +// TODO: Add new types when customer specifies them [JsonConverter(typeof(JsonStringEnumConverter))] public enum WorkshopType { diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IApplicationRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IApplicationRepository.cs index 59c05deb1..1f8ff9c5f 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IApplicationRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IApplicationRepository.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository.Base.Api; +using OutOfSchool.Services.Util; namespace OutOfSchool.Services.Repository.Api; @@ -14,4 +16,6 @@ public interface IApplicationRepository : IEntityRepositorySoftDeleted UpdateAllApprovedApplications(); Task DeleteChildApplications(Guid childId); + + Task> CountTakenSeatsForWorkshops(List workshopIds); } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IProviderRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IProviderRepository.cs index cae185981..d4c251522 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IProviderRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IProviderRepository.cs @@ -12,10 +12,6 @@ public interface IProviderRepository : ISensitiveEntityRepositorySoftDeleted GetWithNavigations(Guid id); - Task> GetAllWithDeleted(DateTime updatedAfter, int from, int size); - - Task CountWithDeleted(DateTime updatedAfter); - Task> CheckExistsByEdrpous(Dictionary edrpous); Task> CheckExistsByEmails(Dictionary emails); diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IWorkshopRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IWorkshopRepository.cs index db164ca3f..2ef4481f6 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IWorkshopRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/Api/IWorkshopRepository.cs @@ -43,8 +43,4 @@ public interface IWorkshopRepository : IEntityRepositorySoftDeletedAmount of available seats for the specified workshop. /// It can throw exception when method get workshopId but Workshop doesn't exist. Task GetAvailableSeats(Guid workshopId); - - Task> GetAllWithDeleted(DateTime updatedAfter, int from, int size); - - Task CountWithDeleted(DateTime updatedAfter); } diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/ApplicationRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/ApplicationRepository.cs index 385e7709f..ad38a0cf4 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/ApplicationRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/ApplicationRepository.cs @@ -7,6 +7,7 @@ using OutOfSchool.Services.Models; using OutOfSchool.Services.Repository.Api; using OutOfSchool.Services.Repository.Base; +using OutOfSchool.Services.Util; namespace OutOfSchool.Services.Repository; @@ -98,4 +99,20 @@ public async Task DeleteChildApplications(Guid childId) await dbContext.SaveChangesAsync().ConfigureAwait(false); } } + + public Task> CountTakenSeatsForWorkshops(List workshopIds) + { + return dbSet + .Where(x => + (x.Status == ApplicationStatus.Approved || x.Status == ApplicationStatus.StudyingForYears) + && !x.IsDeleted + && x.Child != null + && !x.Child.IsDeleted + && x.Parent != null + && !x.Parent.IsDeleted + && workshopIds.Contains(x.WorkshopId)) + .GroupBy(a => a.WorkshopId) + .Select(g => new WorkshopTakenSeats(g.Key, g.Count())) + .ToListAsync(); + } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/ProviderRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/ProviderRepository.cs index 6ec8d979b..fa7a2a46c 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/ProviderRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/ProviderRepository.cs @@ -84,28 +84,6 @@ public async Task GetWithNavigations(Guid id) .SingleOrDefaultAsync(provider => !provider.IsDeleted && provider.Id == id); } - public Task> GetAllWithDeleted(DateTime updatedAfter, int from, int size) - { - IQueryable query = db.Providers; - - query = updatedAfter == default - ? query.Where(provider => !provider.IsDeleted) - : query.Where(provider => provider.UpdatedAt > updatedAfter || provider.Workshops.Any(w => w.UpdatedAt > updatedAfter)); - - return query.Skip(from).Take(size).ToListAsync(); - } - - public Task CountWithDeleted(DateTime updatedAfter) - { - IQueryable query = dbSet; - - query = updatedAfter == default - ? query.Where(provider => !provider.IsDeleted) - : query.Where(provider => provider.UpdatedAt > updatedAfter || provider.Workshops.Any(w => w.UpdatedAt > updatedAfter)); - - return query.CountAsync(); - } - public async Task> CheckExistsByEdrpous(Dictionary edrpous) { var existingEdrpouIpn = await db.Providers diff --git a/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs b/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs index e6a2248e6..c61e639c4 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Repository/WorkshopRepository.cs @@ -96,26 +96,4 @@ public override async Task Create(Workshop workshop) return await Task.FromResult(workshop).ConfigureAwait(false); } - - public Task> GetAllWithDeleted(DateTime updatedAfter, int from, int size) - { - IQueryable query = dbSet; - - query = updatedAfter == default - ? query.Where(workshop => !workshop.IsDeleted) - : query.Where(workshop => workshop.UpdatedAt > updatedAfter || workshop.DeleteDate > updatedAfter); - - return query.Skip(from).Take(size).ToListAsync(); - } - - public Task CountWithDeleted(DateTime updatedAfter) - { - IQueryable query = dbSet; - - query = updatedAfter == default - ? query.Where(workshop => !workshop.IsDeleted) - : query.Where(workshop => workshop.UpdatedAt > updatedAfter || workshop.DeleteDate > updatedAfter); - - return query.CountAsync(); - } } diff --git a/OutOfSchool/OutOfSchool.DataAccess/Util/WorkshopTakenSeats.cs b/OutOfSchool/OutOfSchool.DataAccess/Util/WorkshopTakenSeats.cs new file mode 100644 index 000000000..d572b438b --- /dev/null +++ b/OutOfSchool/OutOfSchool.DataAccess/Util/WorkshopTakenSeats.cs @@ -0,0 +1,5 @@ +using System; + +namespace OutOfSchool.Services.Util; + +public record WorkshopTakenSeats(Guid WorkshopId, int TakenSeats); diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ExternalExportServiceTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ExternalExportServiceTests.cs index 1d0b72cd8..7146b58fe 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ExternalExportServiceTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/ExternalExportServiceTests.cs @@ -4,7 +4,6 @@ using System.Linq.Expressions; using System.Threading.Tasks; using AutoMapper; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -14,9 +13,7 @@ using OutOfSchool.BusinessLogic.Services.AverageRatings; using OutOfSchool.BusinessLogic.Util; using OutOfSchool.BusinessLogic.Util.Mapping; -using OutOfSchool.Services; using OutOfSchool.Services.Models; -using OutOfSchool.Services.Repository; using OutOfSchool.Services.Repository.Api; using OutOfSchool.Tests.Common; using OutOfSchool.Tests.Common.TestDataGenerators; @@ -28,6 +25,7 @@ public class ExternalExportServiceTests private ExternalExportService externalExportService; private Mock mockProviderRepository; private Mock mockWorkshopRepository; + private Mock mockApplicationRepository; private Mock mockAverageRatingService; private IMapper mockMapper; private Mock> mockLogger; @@ -37,6 +35,7 @@ public void Setup() { mockProviderRepository = new Mock(); mockWorkshopRepository = new Mock(); + mockApplicationRepository = new Mock(); mockAverageRatingService = new Mock(); mockMapper = TestHelper.CreateMapperInstanceOfProfileTypes(); mockLogger = new Mock>(); @@ -44,6 +43,7 @@ public void Setup() externalExportService = new ExternalExportService( mockProviderRepository.Object, mockWorkshopRepository.Object, + mockApplicationRepository.Object, mockAverageRatingService.Object, mockMapper, mockLogger.Object); @@ -58,8 +58,8 @@ public async Task GetProviders_ReturnsEmptySearchResult() var fakeProviders = ProvidersGenerator.Generate(0); mockProviderRepository - .Setup(x => x.GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size)) - .ReturnsAsync(fakeProviders); + .Setup(x => x.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Returns(fakeProviders.AsTestAsyncEnumerableQuery()); // Act var result = await externalExportService.GetProviders(updatedAfter, offsetFilter); @@ -80,10 +80,10 @@ public async Task GetProviders_ReturnsSearchResultData() var fakeProviders = ProvidersGenerator.Generate(5); mockProviderRepository - .Setup(x => x.GetAllWithDeleted(It.IsAny(), offsetFilter.From, offsetFilter.Size)) - .ReturnsAsync(fakeProviders); + .Setup(x => x.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Returns(fakeProviders.AsTestAsyncEnumerableQuery()); - mockProviderRepository.Setup(x => x.CountWithDeleted(It.IsAny())).ReturnsAsync(5); + mockProviderRepository.Setup(x => x.Count(It.IsAny>>())).ReturnsAsync(5); // Act var result = await externalExportService.GetProviders(updatedAfter, offsetFilter); @@ -92,43 +92,20 @@ public async Task GetProviders_ReturnsSearchResultData() Assert.IsNotNull(result); Assert.AreEqual(fakeProviders.Count, result.TotalAmount); Assert.AreEqual(fakeProviders.Count, result.Entities.Count); - mockProviderRepository.Verify(x => x.CountWithDeleted(updatedAfter), Times.Once); + mockProviderRepository.Verify(x => x.Count(It.IsAny>>()), Times.Once); } [Test] - public async Task GetProviders_ExceptionInGetProviders_ReturnsEmptySearchResult() + public void GetProviders_ExceptionInGetProviders_ReturnsEmptySearchResult() { // Arrange var updatedAfter = DateTime.UtcNow; var offsetFilter = new OffsetFilter { Size = 10 }; - mockProviderRepository.Setup(repo => repo.GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size)) - .ThrowsAsync(new Exception("Simulated exception")); + mockProviderRepository.Setup(repo => repo.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Throws(new Exception("Simulated exception")); - // Act - var result = await externalExportService.GetProviders(DateTime.Now, new OffsetFilter()); - - // Assert - Assert.NotNull(result); - Assert.AreEqual(0, result?.TotalAmount ?? 0); - Assert.IsEmpty(result?.Entities ?? Enumerable.Empty()); - } - - [Test] - public async Task GetProviders_ProvidersIsNull_ReturnsEmptySearchResult() - { - // Arrange - var updatedAfter = DateTime.UtcNow; - var offsetFilter = new OffsetFilter { Size = 10 }; - mockProviderRepository.Setup(repo => repo.GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size)) - .ReturnsAsync((List)null); - - // Act - var result = await externalExportService.GetProviders(DateTime.Now, new OffsetFilter()); - - // Assert - Assert.NotNull(result); - Assert.AreEqual(0, result?.TotalAmount ?? 0); - Assert.IsEmpty(result?.Entities ?? Enumerable.Empty()); + // Act & Assert + Assert.CatchAsync(() => externalExportService.GetProviders(updatedAfter, new OffsetFilter())); } [Test] @@ -138,10 +115,13 @@ public async Task GetWorkshops_ReturnsEmptySearchResult() var updatedAfter = DateTime.UtcNow; var offsetFilter = new OffsetFilter { Size = 10 }; var fakeWorkshops = WorkshopGenerator.Generate(0); + + mockApplicationRepository.Setup(x => x.CountTakenSeatsForWorkshops(It.IsAny>())) + .ReturnsAsync([]); mockWorkshopRepository - .Setup(x => x.GetAllWithDeleted(updatedAfter, 0, 10)) - .ReturnsAsync(fakeWorkshops); + .Setup(x => x.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Returns(fakeWorkshops.AsTestAsyncEnumerableQuery()); // Act var result = await externalExportService.GetWorkshops(updatedAfter, offsetFilter); @@ -160,12 +140,15 @@ public async Task GetWorkshops_ReturnsSearchResultData() var offsetFilter = new OffsetFilter { Size = 10 }; var fakeWorkshops = WorkshopGenerator.Generate(3); + + mockApplicationRepository.Setup(x => x.CountTakenSeatsForWorkshops(It.IsAny>())) + .ReturnsAsync([]); mockWorkshopRepository - .Setup(x => x.GetAllWithDeleted(updatedAfter, 0, 10)) - .ReturnsAsync(fakeWorkshops); + .Setup(x => x.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Returns(fakeWorkshops.AsTestAsyncEnumerableQuery()); - mockWorkshopRepository.Setup(x => x.CountWithDeleted(It.IsAny())).ReturnsAsync(3); + mockWorkshopRepository.Setup(x => x.Count(It.IsAny>>())).ReturnsAsync(3); // Act var result = await externalExportService.GetWorkshops(updatedAfter, offsetFilter); @@ -174,59 +157,44 @@ public async Task GetWorkshops_ReturnsSearchResultData() Assert.IsNotNull(result); Assert.AreEqual(fakeWorkshops.Count, result.TotalAmount); Assert.AreEqual(fakeWorkshops.Count, result.Entities.Count); - mockWorkshopRepository.Verify(x => x.CountWithDeleted(updatedAfter), Times.Once); + mockWorkshopRepository.Verify(x => x.Count(It.IsAny>>()), Times.Once); } [Test] - public async Task GetWorkshops_ExceptionInGetWorkshops_ReturnsEmptySearchResult() + public void GetWorkshops_ExceptionInGetWorkshops_ReturnsEmptySearchResult() { // Arrange var updatedAfter = DateTime.UtcNow; var offsetFilter = new OffsetFilter { Size = 10 }; - mockWorkshopRepository.Setup(repo => repo.GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size)) - .ThrowsAsync(new Exception("Simulated exception")); - - // Act - var result = await externalExportService.GetWorkshops(DateTime.Now, new OffsetFilter()); + mockWorkshopRepository.Setup(repo => repo.Get(offsetFilter.From, offsetFilter.Size, It.IsAny(), It.IsAny>>(), null, false)) + .Throws(new Exception("Simulated exception")); - // Assert - Assert.NotNull(result); - Assert.AreEqual(0, result?.TotalAmount ?? 0); - Assert.IsEmpty(result?.Entities ?? Enumerable.Empty()); + // Act & Assert + Assert.CatchAsync(() => externalExportService.GetWorkshops(updatedAfter, new OffsetFilter())); } [Test] - public async Task GetWorkshops_ProvidersIsNull_ReturnsEmptySearchResult() + public void Constructor_NullProviderRepository_ThrowsArgumentNullException() { - // Arrange - var updatedAfter = DateTime.UtcNow; - var offsetFilter = new OffsetFilter { Size = 10 }; - mockWorkshopRepository.Setup(repo => repo.GetAllWithDeleted(updatedAfter, offsetFilter.From, offsetFilter.Size)) - .ReturnsAsync((List)null); - - // Act - var result = await externalExportService.GetWorkshops(DateTime.Now, new OffsetFilter()); - - // Assert - Assert.NotNull(result); - Assert.AreEqual(0, result?.TotalAmount ?? 0); - Assert.IsEmpty(result?.Entities ?? Enumerable.Empty()); + // Arrange, Act, Assert + Assert.Throws(() => + new ExternalExportService(null, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of>())); } [Test] - public void Constructor_NullProviderRepository_ThrowsArgumentNullException() + public void Constructor_NullWorkshopRepository_ThrowsArgumentNullException() { // Arrange, Act, Assert Assert.Throws(() => - new ExternalExportService(null, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of>())); + new ExternalExportService(Mock.Of(), null, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of>())); } - + [Test] - public void Constructor_NullWorkshopRepository_ThrowsArgumentNullException() + public void Constructor_NullApplicationRepository_ThrowsArgumentNullException() { // Arrange, Act, Assert Assert.Throws(() => - new ExternalExportService(Mock.Of(), null, Mock.Of(), Mock.Of(), Mock.Of>())); + new ExternalExportService(Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of(), Mock.Of>())); } [Test] @@ -234,7 +202,7 @@ public void Constructor_NullMapper_ThrowsArgumentNullException() { // Arrange, Act, Assert Assert.Throws(() => - new ExternalExportService(Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of>())); + new ExternalExportService(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of>())); } [Test] @@ -242,7 +210,7 @@ public void Constructor_NullLogger_ThrowsArgumentNullException() { // Arrange, Act, Assert Assert.Throws(() => - new ExternalExportService(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null)); + new ExternalExportService(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null)); } [Test] @@ -250,88 +218,6 @@ public void Constructor_NullAverageRatingService_ThrowsArgumentNullException() { // Arrange, Act, Assert Assert.Throws(() => - new ExternalExportService(Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of>())); - } - - [Test] - public async Task GetAllUpdatedProviders_DefaultUpdatedAfter_ReturnsNonDeletedProviders() - { - // Arrange - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(databaseName: "InMemoryTestDatabase") - .Options; - - using (var dbContext = new OutOfSchoolDbContext(options)) - { - var updatedAfter = default(DateTime); - var offsetFilter = new OffsetFilter { Size = 10 }; - var fakeProviders = ProvidersGenerator.Generate(5); - - fakeProviders[0].IsDeleted = true; - fakeProviders[2].IsDeleted = true; - - dbContext.Providers.AddRange(fakeProviders); - dbContext.SaveChanges(); - - var providerRepository = new ProviderRepository(dbContext); - - var externalExportProviderService = new ExternalExportService( - providerRepository, - new Mock().Object, - new Mock().Object, - mockMapper, - new Mock>().Object - ); - - // Act - var result = await externalExportProviderService.GetProviders(updatedAfter, offsetFilter); - - // Assert - Assert.IsNotNull(result); - Assert.AreEqual(fakeProviders.Count - 2, result.TotalAmount); - Assert.AreEqual(fakeProviders.Count - 2, result.Entities.Count); - Assert.IsTrue(result.Entities.All(provider => !provider.IsDeleted)); - } - } - - [Test] - public async Task GetAllUpdatedWorkshops_DefaultUpdatedAfter_ReturnsNonDeletedWorkshops() - { - // Arrange - var options = new DbContextOptionsBuilder() - .UseInMemoryDatabase(databaseName: "InMemoryTestDatabase") - .Options; - - using (var dbContext = new OutOfSchoolDbContext(options)) - { - var updatedAfter = default(DateTime); - var offsetFilter = new OffsetFilter { Size = 10 }; - var fakeWorkshops = WorkshopGenerator.Generate(3); - - fakeWorkshops[0].IsDeleted = true; - fakeWorkshops[2].IsDeleted = true; - - dbContext.Workshops.AddRange(fakeWorkshops); - dbContext.SaveChanges(); - - var workshopRepository = new WorkshopRepository(dbContext); - - var externalExportProviderService = new ExternalExportService( - new Mock().Object, - workshopRepository, - new Mock().Object, - mockMapper, - new Mock>().Object - ); - - // Act - var result = await externalExportProviderService.GetWorkshops(updatedAfter, offsetFilter); - - // Assert - Assert.IsNotNull(result); - Assert.AreEqual(fakeWorkshops.Count - 2, result.TotalAmount); - Assert.AreEqual(fakeWorkshops.Count - 2, result.Entities.Count); - Assert.IsTrue(result.Entities.All(provider => !provider.IsDeleted)); - } + new ExternalExportService(Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of>())); } } \ No newline at end of file