| @@ -0,0 +1,53 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| public static class AdExtensions | |||
| { | |||
| public static IQueryable<Ad> FilterByExperience(this IQueryable<Ad> query, int minExperience, int maxExperience) => | |||
| minExperience >= maxExperience ? query.Where(x => x.MinimumExperience >= minExperience && x.MinimumExperience <= maxExperience) | |||
| : query.Where(x => x.MinimumExperience >= minExperience && x.MinimumExperience <= maxExperience); | |||
| public static IQueryable<Ad> FilterByWorkType(this IQueryable<Ad> query, string workHour) => | |||
| workHour.ToLower() == "parttime" ? query.Where(x => x.WorkHour == WorkHours.PartTime) : query.Where(x => x.WorkHour == WorkHours.FullTime); | |||
| public static IQueryable<Ad> FilterByEmploymentType(this IQueryable<Ad> query, string employmentType) => | |||
| employmentType.ToLower() == "intership" ? query.Where(x => x.EmploymentType == EmploymentTypes.Intership) : query.Where(x => x.EmploymentType == EmploymentTypes.Work); | |||
| public static List<Ad> FilterByTechnologies(this List<Ad> query, string[] technologies) | |||
| { | |||
| if (technologies.Length == 0) | |||
| { | |||
| return query; | |||
| } | |||
| List<Ad> filteredAds = new List<Ad>(); | |||
| for (int i = 0; i < query.Count(); i++) | |||
| { | |||
| for (int j = 0; j < query[i].Technologies.Count(); j++) | |||
| { | |||
| var s = 0; | |||
| for (int k = 0; k < technologies.Length; k++) | |||
| { | |||
| if (query[i].Technologies[j].Name.ToLower() == technologies[k].ToLower()) | |||
| { | |||
| s = 1; | |||
| } | |||
| } | |||
| if (s == 1) | |||
| { | |||
| filteredAds.Add(query[i]); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return filteredAds; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,18 +1,25 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| using Diligent.WebAPI.Business.Extensions; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class AdService : IAdService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ITechnologyService _technologyService; | |||
| public AdService(DatabaseContext context, IMapper mapper) | |||
| public AdService(DatabaseContext context, IMapper mapper, ITechnologyService technologyService) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _technologyService = technologyService; | |||
| } | |||
| public async Task<List<AdResponseDto>> GetAllAsync() => | |||
| _mapper.Map<List<AdResponseDto>>(await _context.Ads.Include(x => x.Technologies).ToListAsync()); | |||
| public async Task<List<AdResponseDto>> GetAllAsync() | |||
| { | |||
| var today = DateTime.Now; | |||
| return _mapper.Map<List<AdResponseDto>>(await _context.Ads.Include(x => x.Technologies).Where(x => x.ExpiredAt > today).ToListAsync()); | |||
| } | |||
| public async Task<AdResponseDto> GetByIdAsync(int id) | |||
| { | |||
| @@ -43,9 +50,30 @@ | |||
| return _mapper.Map<List<AdResponseDto>>(archiveAds); | |||
| } | |||
| public async Task<List<AdResponseDto>> GetFilteredAdsAsync(AdFilterDto filters) | |||
| { | |||
| var filteredAds = await _context.Ads.Include(x => x.Technologies) | |||
| .FilterByExperience(filters.MinExperience, filters.MaxExperience) | |||
| .FilterByWorkType(filters.WorkHour) | |||
| .FilterByEmploymentType(filters.EmploymentType) | |||
| .ToListAsync(); | |||
| filteredAds = filteredAds.FilterByTechnologies(filters.Technologies); | |||
| return _mapper.Map<List<AdResponseDto>>(filteredAds); | |||
| } | |||
| public async Task CreateAsync(AdCreateDto adCreateDto) | |||
| { | |||
| await _context.Ads.AddAsync(_mapper.Map<Ad>(adCreateDto)); | |||
| var ad = _mapper.Map<Ad>(adCreateDto); | |||
| for (int i = 0; i < adCreateDto.TechnologiesIds.Count; i++) | |||
| { | |||
| var technology = await _technologyService.GetEntityByIdAsync(adCreateDto.TechnologiesIds[i]); | |||
| ad.Technologies.Add(technology); | |||
| } | |||
| await _context.Ads.AddAsync(ad); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| @@ -11,6 +11,8 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task<List<AdResponseDto>> GetArchiveAds(); | |||
| Task<List<AdResponseDto>> GetFilteredAdsAsync(AdFilterDto filters); | |||
| Task CreateAsync(AdCreateDto adCreateDto); | |||
| Task UpdateAsync(int id, AdUpdateDto adUpdateDto); | |||
| @@ -8,5 +8,7 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task<TechnologyResponseDto> GetByIdAsync(int id); | |||
| Task<TechnologyApplicantViewDto> GetByIdAsync2(int id); | |||
| Task<Technology> GetEntityByIdAsync(int id); | |||
| } | |||
| } | |||
| @@ -43,5 +43,15 @@ namespace Diligent.WebAPI.Business.Services | |||
| return _mapper.Map<TechnologyApplicantViewDto>(technology); | |||
| } | |||
| public async Task<Technology> GetEntityByIdAsync(int id) | |||
| { | |||
| var technology = await _context.Technologies.FindAsync(id); | |||
| if (technology is null) | |||
| throw new EntityNotFoundException("Technology not found"); | |||
| return technology; | |||
| } | |||
| } | |||
| } | |||
| @@ -21,5 +21,11 @@ namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| public string Requirements { get; set; } | |||
| public string Offer { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| public List<int> TechnologiesIds { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdFilterDto | |||
| { | |||
| public int MinExperience { get; set; } | |||
| public int MaxExperience { get; set; } | |||
| public string[]? Technologies { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -26,5 +26,9 @@ namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| public string Offer { get; set; } | |||
| public List<TechnologyResponseDto> Technologies { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -9,6 +9,9 @@ namespace Diligent.WebAPI.Contracts.DTOs.Technology | |||
| public class TechnologyResponseDto | |||
| { | |||
| public int TechnologyId { get; set; } | |||
| public string TechnologyType { get; set; } | |||
| public string Name { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Data.Configurations | |||
| { | |||
| public class AdConfiguration : IEntityTypeConfiguration<Ad> | |||
| { | |||
| public void Configure(EntityTypeBuilder<Ad> builder) | |||
| { | |||
| builder.Property(c => c.WorkHour).HasConversion<string>(); | |||
| builder.Property(c => c.EmploymentType).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -7,6 +7,7 @@ namespace Diligent.WebAPI.Data.Configurations | |||
| public void Configure(EntityTypeBuilder<Technology> builder) | |||
| { | |||
| builder.Property(c => c.Name).HasMaxLength(128); | |||
| builder.Property(c => c.TechnologyType).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -35,5 +35,6 @@ public class DatabaseContext : IdentityDbContext<User, AppRole, int> | |||
| modelBuilder.ApplyConfiguration(new TechnologyConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new CommentConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new UserConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new AdConfiguration()); | |||
| } | |||
| } | |||
| @@ -1,6 +1,10 @@ | |||
| | |||
| namespace Diligent.WebAPI.Data.Entities | |||
| { | |||
| public enum WorkHours { PartTime, FullTime }; | |||
| public enum EmploymentTypes { Intership, Work }; | |||
| public class Ad | |||
| { | |||
| public int Id { get; set; } | |||
| @@ -22,5 +26,9 @@ namespace Diligent.WebAPI.Data.Entities | |||
| public List<Technology> Technologies { get; set; } = new(); | |||
| public List<Applicant> Applicants { get; set; } = new(); | |||
| public WorkHours WorkHour { get; set; } | |||
| public EmploymentTypes EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -1,9 +1,12 @@ | |||
| namespace Diligent.WebAPI.Data.Entities | |||
| { | |||
| public enum TechnologyTypes { Backend, Frontend, Other }; | |||
| public class Technology | |||
| { | |||
| public int TechnologyId { get; set; } | |||
| public string Name { get; set; } | |||
| public TechnologyTypes TechnologyType { get; set; } | |||
| public List<TechnologyApplicant> TechnologyApplicants { get; set; } | |||
| public List<Ad> Ads { get; set; } = new(); | |||
| @@ -0,0 +1,48 @@ | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| #nullable disable | |||
| namespace Diligent.WebAPI.Data.Migrations | |||
| { | |||
| public partial class AddedEnumsForAdAndTechnologies : Migration | |||
| { | |||
| protected override void Up(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.AddColumn<string>( | |||
| name: "TechnologyType", | |||
| table: "Technologies", | |||
| type: "nvarchar(max)", | |||
| nullable: false, | |||
| defaultValue: ""); | |||
| migrationBuilder.AddColumn<string>( | |||
| name: "EmploymentType", | |||
| table: "Ads", | |||
| type: "nvarchar(max)", | |||
| nullable: false, | |||
| defaultValue: ""); | |||
| migrationBuilder.AddColumn<string>( | |||
| name: "WorkHour", | |||
| table: "Ads", | |||
| type: "nvarchar(max)", | |||
| nullable: false, | |||
| defaultValue: ""); | |||
| } | |||
| protected override void Down(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.DropColumn( | |||
| name: "TechnologyType", | |||
| table: "Technologies"); | |||
| migrationBuilder.DropColumn( | |||
| name: "EmploymentType", | |||
| table: "Ads"); | |||
| migrationBuilder.DropColumn( | |||
| name: "WorkHour", | |||
| table: "Ads"); | |||
| } | |||
| } | |||
| } | |||
| @@ -63,6 +63,10 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.Property<DateTime>("CreatedAt") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<string>("EmploymentType") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime>("ExpiredAt") | |||
| .HasColumnType("datetime2"); | |||
| @@ -85,6 +89,10 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("WorkHour") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("Ads"); | |||
| @@ -499,6 +507,10 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| .HasMaxLength(128) | |||
| .HasColumnType("nvarchar(128)"); | |||
| b.Property<string>("TechnologyType") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("TechnologyId"); | |||
| b.ToTable("Technologies"); | |||
| @@ -29,6 +29,10 @@ namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| public async Task<IActionResult> GetArchiveAds() => | |||
| Ok(await _adService.GetArchiveAds()); | |||
| [HttpGet("filtered")] | |||
| public async Task<IActionResult> GetFilteredAds([FromQuery] AdFilterDto request) => | |||
| Ok(await _adService.GetFilteredAdsAsync(request)); | |||
| [HttpPost] | |||
| public async Task<IActionResult> Create([FromBody]AdCreateDto request) | |||
| { | |||