Skip to content
This repository has been archived by the owner on Oct 14, 2022. It is now read-only.

Commit

Permalink
Merge pull request #10 from futureleadersupc/feat/jobs
Browse files Browse the repository at this point in the history
feat(jobs): Job offers endpoint
  • Loading branch information
dalbitresb12 authored Jun 11, 2022
2 parents 1c2ef1f + a259e01 commit 42f8521
Show file tree
Hide file tree
Showing 16 changed files with 356 additions and 0 deletions.
50 changes: 50 additions & 0 deletions WAW.API/Job/Controllers/OffersController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Domain.Services;
using WAW.API.Job.Resources;
using WAW.API.Shared.Extensions;

namespace WAW.API.Job.Controllers;

[ApiController]
[Route("[controller]")]
public class OffersController : ControllerBase {
private readonly IOfferService service;
private readonly IMapper mapper;

public OffersController(IOfferService service, IMapper mapper) {
this.service = service;
this.mapper = mapper;
}

[HttpGet]
public async Task<IEnumerable<OfferResource>> GetAll() {
var offers = await service.ListAll();
return mapper.Map<IEnumerable<Offer>, IEnumerable<OfferResource>>(offers);
}

[HttpPost]
public async Task<IActionResult> Post([FromBody] OfferRequest resource) {
if (!ModelState.IsValid) return BadRequest(ModelState.GetErrorMessages());

var offer = mapper.Map<OfferRequest, Offer>(resource);
var result = await service.Create(offer);
return result.ToResponse<OfferResource>(this, mapper);
}

[HttpPut("{id:int}")]
public async Task<IActionResult> Put(int id, [FromBody] OfferRequest resource) {
if (!ModelState.IsValid) return BadRequest(ModelState.GetErrorMessages());

var offer = mapper.Map<OfferRequest, Offer>(resource);
var result = await service.Update(id, offer);
return result.ToResponse<OfferResource>(this, mapper);
}

[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteAsync(int id) {
var result = await service.Delete(id);
return result.ToResponse<OfferResource>(this, mapper);
}
}
11 changes: 11 additions & 0 deletions WAW.API/Job/Domain/Models/Offer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using WAW.API.Shared.Domain.Model;

namespace WAW.API.Job.Domain.Models;

public class Offer : BaseModel {
public string Title { get; set; } = string.Empty;
public string? Image { get; set; }
public string? Description { get; set; }
public string SalaryRange { get; set; } = string.Empty;
public bool Status { get; set; }
}
15 changes: 15 additions & 0 deletions WAW.API/Job/Domain/Repositories/IOfferRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using WAW.API.Job.Domain.Models;

namespace WAW.API.Job.Domain.Repositories;

public interface IOfferRepository {
Task<IEnumerable<Offer>> ListAll();

Task Add(Offer offer);

Task<Offer?> FindById(long id);

void Update(Offer offer);

void Remove(Offer offer);
}
9 changes: 9 additions & 0 deletions WAW.API/Job/Domain/Services/Communication/OfferResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using WAW.API.Job.Domain.Models;
using WAW.API.Shared.Domain.Service.Communication;

namespace WAW.API.Job.Domain.Services.Communication;

public class OfferResponse : BaseResponse<Offer> {
public OfferResponse(string message) : base(message) {}
public OfferResponse(Offer resource) : base(resource) {}
}
11 changes: 11 additions & 0 deletions WAW.API/Job/Domain/Services/IOfferService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Domain.Services.Communication;

namespace WAW.API.Job.Domain.Services;

public interface IOfferService {
Task<IEnumerable<Offer>> ListAll();
Task<OfferResponse> Create(Offer offer);
Task<OfferResponse> Update(long id, Offer offer);
Task<OfferResponse> Delete(long id);
}
11 changes: 11 additions & 0 deletions WAW.API/Job/Mapping/ModelToResourceProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using AutoMapper;
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Resources;

namespace WAW.API.Job.Mapping;

public class ModelToResourceProfile : Profile {
public ModelToResourceProfile() {
CreateMap<Offer, OfferResource>();
}
}
11 changes: 11 additions & 0 deletions WAW.API/Job/Mapping/ResourceToModelProfile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using AutoMapper;
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Resources;

namespace WAW.API.Job.Mapping;

public class ResourceToModelProfile : Profile {
public ResourceToModelProfile() {
CreateMap<OfferRequest, Offer>();
}
}
31 changes: 31 additions & 0 deletions WAW.API/Job/Persistence/Repositories/OfferRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Domain.Repositories;
using WAW.API.Weather.Persistence.Contexts;
using WAW.API.Weather.Persistence.Repositories;

namespace WAW.API.Job.Persistence.Repositories;

public class OfferRepository : BaseRepository, IOfferRepository {
public OfferRepository(AppDbContext context) : base(context) {}

public async Task<IEnumerable<Offer>> ListAll() {
return await context.Offers.ToListAsync();
}

public async Task Add(Offer offer) {
await context.Offers.AddAsync(offer);
}

public async Task<Offer?> FindById(long id) {
return await context.Offers.FindAsync(id);
}

public void Update(Offer offer) {
context.Offers.Update(offer);
}

public void Remove(Offer offer) {
context.Offers.Remove(offer);
}
}
19 changes: 19 additions & 0 deletions WAW.API/Job/Resources/OfferRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;

namespace WAW.API.Job.Resources;

public class OfferRequest {
[Required]
public string? Title { get; set; }

[Required]
public string? Image { get; set; }

[Required]
public string? Description { get; set; }

public string? SalaryRange { get; set; }

[Required]
public bool? Status { get; set; }
}
10 changes: 10 additions & 0 deletions WAW.API/Job/Resources/OfferResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace WAW.API.Job.Resources;

public class OfferResource {
public long Id { get; set; }
public string Title { get; set; } = string.Empty;
public string? Image { get; set; }
public string? Description { get; set; }
public string SalaryRange { get; set; } = string.Empty;
public bool Status { get; set; }
}
60 changes: 60 additions & 0 deletions WAW.API/Job/Services/OfferService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using WAW.API.Job.Domain.Models;
using WAW.API.Job.Domain.Repositories;
using WAW.API.Job.Domain.Services;
using WAW.API.Job.Domain.Services.Communication;
using WAW.API.Weather.Domain.Repositories;


namespace WAW.API.Job.Services;

public class OfferService : IOfferService {
private readonly IOfferRepository repository;
private readonly IUnitOfWork unitOfWork;

public OfferService(IOfferRepository repository, IUnitOfWork unitOfWork) {
this.repository = repository;
this.unitOfWork = unitOfWork;
}

public Task<IEnumerable<Offer>> ListAll() {
return repository.ListAll();
}

public async Task<OfferResponse> Create(Offer offer) {
try {
await repository.Add(offer);
await unitOfWork.Complete();
return new OfferResponse(offer);
} catch (Exception e) {
return new OfferResponse($"An error occurred while saving the offer: {e.Message}");
}
}

public async Task<OfferResponse> Update(long id, Offer offer) {
var current = await repository.FindById(id);
if (current == null) return new OfferResponse("Offer not found");

offer.CopyProperties(current);

try {
repository.Update(current);
await unitOfWork.Complete();
return new OfferResponse(current);
} catch (Exception e) {
return new OfferResponse($"An error occurred while updating the offer: {e.Message}");
}
}

public async Task<OfferResponse> Delete(long id) {
var current = await repository.FindById(id);
if (current == null) return new OfferResponse("Offer not found");

try {
repository.Remove(current);
await unitOfWork.Complete();
return new OfferResponse(current);
} catch (Exception e) {
return new OfferResponse($"An error occurred while deleting the offer: {e.Message}");
}
}
}
51 changes: 51 additions & 0 deletions WAW.API/Migrations/20220610184650_CreateJobs.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions WAW.API/Migrations/20220610184650_CreateJobs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace WAW.API.Migrations
{
public partial class CreateJobs : Migration
{
protected override void Up(MigrationBuilder migrationBuilder) {
migrationBuilder.CreateTable(
name: "jobs",
columns: table => new {
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
title = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false),
image = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: false),
description = table.Column<string>(type: "longtext", nullable: false).Annotation("MySql:CharSet", "utf8mb4"),
salaryRange = table.Column<string>(type: "varchar(400)",maxLength: 400, nullable: true),
status = table.Column<bool>(type: "boolean", nullable: false),

},
constraints: table => { table.PrimaryKey("p_k_jobs", x => x.id); }
)
.Annotation("MySql:Charset", "utf8mb4");

}

protected override void Down(MigrationBuilder migrationBuilder) {
migrationBuilder.DropTable(name: "jobs");
}
}
}
13 changes: 13 additions & 0 deletions WAW.API/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using WAW.API.Job.Domain.Repositories;
using WAW.API.Job.Domain.Services;
using WAW.API.Job.Persistence.Repositories;
using WAW.API.Job.Services;
using WAW.API.Company.Domain.Repositories;
using WAW.API.Company.Domain.Services;
using WAW.API.Company.Persistence.Repositories;
Expand All @@ -12,6 +16,8 @@
using WAW.API.Weather.Persistence.Contexts;
using WAW.API.Weather.Persistence.Repositories;
using WAW.API.Weather.Services;
using IUnitOfWork = WAW.API.Weather.Domain.Repositories.IUnitOfWork;
using UnitOfWork = WAW.API.Weather.Persistence.Repositories.UnitOfWork;

var builder = WebApplication.CreateBuilder(args);

Expand Down Expand Up @@ -60,6 +66,9 @@
builder.Services.AddScoped<IForecastRepository, ForecastRepository>();
builder.Services.AddScoped<IForecastService, ForecastService>();

builder.Services.AddScoped<IOfferRepository, OfferRepository>();
builder.Services.AddScoped<IOfferService, OfferService>();

builder.Services.AddScoped<ICompanyRepository, CompanyRepository>();
builder.Services.AddScoped<ICompanyService, CompanyService>();

Expand All @@ -71,6 +80,10 @@
typeof(WAW.API.Company.Mapping.ModelToResourceProfile),
typeof(WAW.API.Company.Mapping.ResourceToModelProfile)
);
builder.Services.AddAutoMapper(
typeof(WAW.API.Job.Mapping.ModelToResourceProfile),
typeof(WAW.API.Job.Mapping.ResourceToModelProfile)
);

var app = builder.Build();

Expand Down
5 changes: 5 additions & 0 deletions WAW.API/WAW.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<ItemGroup>
<InternalsVisibleTo Include="WAW.API.Tests" />
</ItemGroup>
<ItemGroup>
<Folder Include="Job\Controllers" />
<Folder Include="Job\Domain\Models" />
<Folder Include="Job\Domain\Repositories" />
</ItemGroup>
<ItemGroup>
<Folder Include="Company\Controllers" />
</ItemGroup>
Expand Down
Loading

0 comments on commit 42f8521

Please sign in to comment.