diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/DirectionConfiguration.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/DirectionConfiguration.cs new file mode 100644 index 0000000000..db1dc89af6 --- /dev/null +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/DirectionConfiguration.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace OutOfSchool.Services.Models.Configurations; + +internal class DirectionConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + + builder.HasIndex(x => x.IsDeleted); + + builder.Property(x => x.IsDeleted).HasDefaultValue(false); + } +} \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/FavoriteConfiguration.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/FavoriteConfiguration.cs index 86f6c41dc5..dd5f873ac4 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/FavoriteConfiguration.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/Configurations/FavoriteConfiguration.cs @@ -1,5 +1,5 @@ -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace OutOfSchool.Services.Models.Configurations; diff --git a/OutOfSchool/OutOfSchool.DataAccess/Models/Direction.cs b/OutOfSchool/OutOfSchool.DataAccess/Models/Direction.cs index 9de538c0f0..72d5c4da6a 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/Models/Direction.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/Models/Direction.cs @@ -17,5 +17,7 @@ public class Direction : IKeyedEntity [MaxLength(500)] public string Description { get; set; } = string.Empty; + public bool IsDeleted { get; set; } + public virtual List InstitutionHierarchies { get; set; } } \ No newline at end of file diff --git a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.SoftDelete.cs b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.SoftDelete.cs index d57e8dfcd6..a4f88a52dd 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.SoftDelete.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.SoftDelete.cs @@ -58,7 +58,7 @@ private void ApplySoftDelete(ModelBuilder builder) .ApplySoftDelete() .ApplySoftDelete() .ApplySoftDelete() - .ApplySoftDelete() + //.ApplySoftDelete() //.ApplySoftDelete() //.ApplySoftDelete() .ApplySoftDelete() diff --git a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs index 411e40022f..5fe1aff7da 100644 --- a/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs +++ b/OutOfSchool/OutOfSchool.DataAccess/OutOfSchoolDbContext.cs @@ -130,6 +130,7 @@ protected override void OnModelCreating(ModelBuilder builder) builder.ApplyConfiguration(new ChatRoomWorkshopConfiguration()); builder.ApplyConfiguration(new ChildConfiguration()); builder.ApplyConfiguration(new CodeficatorConfiguration()); + builder.ApplyConfiguration(new DirectionConfiguration()); builder.ApplyConfiguration(new EntityImagesConfiguration()); builder.ApplyConfiguration(new EntityImagesConfiguration()); builder.ApplyConfiguration(new FavoriteConfiguration()); diff --git a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/DirectionServiceTests.cs b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/DirectionServiceTests.cs index 5ead47e4ca..51a65285cf 100644 --- a/OutOfSchool/OutOfSchool.WebApi.Tests/Services/DirectionServiceTests.cs +++ b/OutOfSchool/OutOfSchool.WebApi.Tests/Services/DirectionServiceTests.cs @@ -13,6 +13,7 @@ using OutOfSchool.Services.Models; using OutOfSchool.Services.Models.SubordinationStructure; using OutOfSchool.Services.Repository; +using OutOfSchool.Tests.Common; using OutOfSchool.WebApi.Models; using OutOfSchool.WebApi.Services; @@ -168,11 +169,11 @@ public async Task Update_WhenEntityIsValid_UpdatesExistedEntity() Id = 1, Title = "ChangedTitle1", }; - var expected = new Direction() - { - Id = 1, - Title = "NewTitle", - }; + + var expected = (await repo.GetByFilter( + d => !d.IsDeleted && d.Id == changedEntity.Id) + .ConfigureAwait(false)).SingleOrDefault(); + mapper.Setup(m => m.Map(changedEntity)).Returns(expected); mapper.Setup(m => m.Map(expected)).Returns(changedEntity); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs index f5a3051d1b..939b51ceec 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/Database/WorkshopService.cs @@ -671,7 +671,7 @@ private Expression> PredicateBuild(WorkshopFilter filter) var tempPredicate = PredicateBuilder.False(); foreach (var direction in filter.DirectionIds) { - tempPredicate = tempPredicate.Or(x => x.InstitutionHierarchy.Directions.Any(d => d.Id == direction)); + tempPredicate = tempPredicate.Or(x => x.InstitutionHierarchy.Directions.Any(d => !d.IsDeleted && d.Id == direction)); } predicate = predicate.And(tempPredicate); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/DirectionService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/DirectionService.cs index f6bb3a41b5..c91048698e 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/DirectionService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/DirectionService.cs @@ -1,12 +1,9 @@ -using System; -using System.Linq.Expressions; +using System.Linq.Expressions; using AutoMapper; using Microsoft.Extensions.Localization; -using Nest; using OutOfSchool.Services.Enums; using OutOfSchool.WebApi.Common; using OutOfSchool.WebApi.Models; -using OutOfSchool.WebApi.Util; namespace OutOfSchool.WebApi.Services; @@ -76,7 +73,8 @@ public async Task> Delete(long id) { logger.LogInformation($"Deleting Direction with Id = {id} started."); - var direction = await repository.GetById(id).ConfigureAwait(false); + var directions = await repository.GetByFilter(x => !x.IsDeleted && x.Id == id).ConfigureAwait(false); + var direction = directions.SingleOrDefault(); if (direction == null) { @@ -120,7 +118,7 @@ public async Task> GetAll() { logger.LogInformation("Getting all Directions started."); - var directions = await repository.GetAll().ConfigureAwait(false); + var directions = await repository.GetByFilter(x => !x.IsDeleted).ConfigureAwait(false); logger.LogInformation(!directions.Any() ? "Direction table is empty." @@ -181,7 +179,8 @@ public async Task GetById(long id) { logger.LogInformation($"Getting Direction by Id started. Looking Id = {id}."); - var direction = await repository.GetById((int)id).ConfigureAwait(false); + var directions = await repository.GetByFilter(x => !x.IsDeleted && x.Id == (int)id).ConfigureAwait(false); + var direction = directions.SingleOrDefault(); if (direction == null) { @@ -200,24 +199,26 @@ public async Task Update(DirectionDto dto) { logger.LogInformation($"Updating Direction with Id = {dto?.Id} started."); - try - { - var direction = await repository.Update(mapper.Map(dto)).ConfigureAwait(false); - - logger.LogInformation($"Direction with Id = {direction?.Id} updated succesfully."); + var directions = await repository.GetByFilter(x => !x.IsDeleted && x.Id == dto.Id).ConfigureAwait(false); + var direction = directions.SingleOrDefault(); - return mapper.Map(direction); - } - catch (DbUpdateConcurrencyException) + if (direction is null) { logger.LogError($"Updating failed. Direction with Id = {dto?.Id} doesn't exist in the system."); - throw; + throw new DbUpdateConcurrencyException($"Updating failed. Direction with Id = {dto?.Id} doesn't exist in the system."); } + + mapper.Map(dto, direction); + direction = await repository.Update(direction).ConfigureAwait(false); + + logger.LogInformation($"Direction with Id = {direction?.Id} updated succesfully."); + + return mapper.Map(direction); } private void DirectionValidation(DirectionDto dto) { - if (repository.Get(where: x => x.Title == dto.Title).Any()) + if (repository.Get(where: x => !x.IsDeleted && x.Title == dto.Title).Any()) { throw new ArgumentException(localizer["There is already a Direction with such a data."]); } @@ -227,6 +228,8 @@ private void DirectionValidation(DirectionDto dto) { Expression> predicate = PredicateBuilder.True(); + predicate = predicate.And(direction => !direction.IsDeleted); + if (!string.IsNullOrWhiteSpace(filter.Name)) { predicate = predicate @@ -260,7 +263,7 @@ private void DirectionValidation(DirectionDto dto) workshopCountFilter = workshopCountFilter .And(w => w.Address.CATOTTGId == filter.CatottgId); } - + return (predicate, workshopCountFilter); } } diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/FavoriteService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/FavoriteService.cs index 3740142a85..6e3979a1c6 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/FavoriteService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/FavoriteService.cs @@ -143,7 +143,7 @@ public async Task Update(FavoriteDto dto) } mapper.Map(dto, favorite); - favorite = await favoriteRepository.Update(mapper.Map(dto)).ConfigureAwait(false); + favorite = await favoriteRepository.Update(favorite).ConfigureAwait(false); logger.LogInformation($"Favorite with Id = {favorite?.Id} updated succesfully."); diff --git a/OutOfSchool/OutOfSchool.WebApi/Services/StatisticService.cs b/OutOfSchool/OutOfSchool.WebApi/Services/StatisticService.cs index b7c72c3e76..93df91192a 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Services/StatisticService.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Services/StatisticService.cs @@ -81,6 +81,7 @@ public async Task> GetPopularDirectionsFromDatabase(in var directionsWithWorkshops = workshops .SelectMany(w => w.InstitutionHierarchy.Directions) + .Where(d => !d.IsDeleted) .GroupBy(d => d.Id) .Select(g => new { @@ -90,6 +91,7 @@ public async Task> GetPopularDirectionsFromDatabase(in var directionsWithApplications = applications .SelectMany(a => a.Workshop.InstitutionHierarchy.Directions) + .Where(d => !d.IsDeleted) .GroupBy(d => d.Id) .Select(g => new { @@ -116,7 +118,7 @@ public async Task> GetPopularDirectionsFromDatabase(in WorkshopsCount = x.directionWithWorkshop.WorkshopsCount, }); - var allDirections = directionRepository.Get(); + var allDirections = directionRepository.Get(where: d => !d.IsDeleted); var statistics = allDirections .GroupJoin( diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/Mapping/ElasticProfile.cs b/OutOfSchool/OutOfSchool.WebApi/Util/Mapping/ElasticProfile.cs index 019a5b60ec..b19fe69be9 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Util/Mapping/ElasticProfile.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Util/Mapping/ElasticProfile.cs @@ -144,7 +144,7 @@ public ElasticProfile() .ForMember(dest => dest.InstitutionHierarchy, opt => opt.MapFrom(src => src.InstitutionHierarchy.Title)) .ForMember( dest => dest.DirectionIds, - opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Select(d => d.Id))) + opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Where(x => !x.IsDeleted).Select(d => d.Id))) .ForMember(dest => dest.InstitutionId, opt => opt.MapFrom(src => src.InstitutionHierarchy.InstitutionId)) .ForMember(dest => dest.Institution, opt => opt.MapFrom(src => src.InstitutionHierarchy.Institution.Title)) .ForMember( diff --git a/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs index f0d0e116e3..0d6436124c 100644 --- a/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs +++ b/OutOfSchool/OutOfSchool.WebApi/Util/MappingProfile.cs @@ -70,7 +70,7 @@ public MappingProfile() .ForMember(dest => dest.ImageIds, opt => opt.MapFrom(src => src.Images.Select(x => x.ExternalStorageId))) .ForMember(dest => dest.InstitutionHierarchy, opt => opt.MapFrom(src => src.InstitutionHierarchy.Title)) .ForMember(dest => dest.DirectionIds, - opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Select(d => d.Id))) + opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Where(x => !x.IsDeleted).Select(d => d.Id))) .ForMember(dest => dest.InstitutionId, opt => opt.MapFrom(src => src.InstitutionHierarchy.InstitutionId)) .ForMember(dest => dest.Institution, opt => opt.MapFrom(src => src.InstitutionHierarchy.Institution.Title)) .ForMember(dest => dest.CoverImage, opt => opt.Ignore()) @@ -220,7 +220,7 @@ public MappingProfile() .ForMember(dest => dest.WorkshopId, opt => opt.MapFrom(s => s.Id)) .ForMember(dest => dest.CoverImageId, opt => opt.MapFrom(s => s.CoverImageId)) .ForMember(dest => dest.DirectionIds, - opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Select(x => x.Id))) + opt => opt.MapFrom(src => src.InstitutionHierarchy.Directions.Where(x => !x.IsDeleted).Select(x => x.Id))) .ForMember(dest => dest.Rating, opt => opt.Ignore()) .ForMember(dest => dest.NumberOfRatings, opt => opt.Ignore()) .ForMember(dest => dest.ProviderLicenseStatus, opt => @@ -305,7 +305,8 @@ public MappingProfile() .ForMember(dest => dest.MiddleName, opt => opt.MapFrom(src => src.MiddleName ?? string.Empty)); CreateMap() - .ForMember(dest => dest.InstitutionHierarchies, opt => opt.Ignore()); + .ForMember(dest => dest.InstitutionHierarchies, opt => opt.Ignore()) + .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()); CreateMap() .ForMember(dest => dest.WorkshopsCount, opt => opt.Ignore());