Merge pull request 'feat/model_api' (#30) from feat/model_api into master

This commit is contained in:
Zonar 2020-08-10 19:09:18 +02:00
commit 95c08da571
19 changed files with 304 additions and 62 deletions

View File

@ -1,40 +1,65 @@
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading;
// using System.Threading.Tasks;
// using InternshipSystem.Api.Queries;
// using InternshipSystem.Core;
// using InternshipSystem.Repository;
// using Microsoft.AspNetCore.Http;
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.EntityFrameworkCore;
//
// namespace InternshipSystem.Api.Controllers
// {
// [ApiController]
// [Route("companies")]
// public class CompaniesController : ControllerBase
// {
// public CompaniesController(InternshipDbContext context)
// {
// Context = context;
// }
// private InternshipDbContext Context { get; }
//
// /// <summary>
// /// Get companies matching provided paginated query
// /// </summary>
// /// <param name="searchQuery">Paginated query description</param>
// /// <returns>Part of companies collection</returns>
// [HttpGet]
// [ProducesResponseType(StatusCodes.Status200OK)]
// public async Task<IReadOnlyCollection<Company>> SearchByNameAsync([FromQuery] SearchQuery searchQuery, CancellationToken cancellationToken) =>
// await Context.Companies
// .Where(c => c.Name.ToLower().Contains(searchQuery.Query.ToLower()))
// .OrderBy(o => o.Name)
// .Skip(searchQuery.Page * searchQuery.PerPage)
// .Take(searchQuery.PerPage)
// .ToListAsync(cancellationToken);
// }
//
// }
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using InternshipSystem.Api.Queries;
using InternshipSystem.Core;
using InternshipSystem.Repository;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace InternshipSystem.Api.Controllers
{
[ApiController]
[Route("companies")]
public class CompaniesController : ControllerBase
{
public CompaniesController(InternshipDbContext context)
{
Context = context;
}
private InternshipDbContext Context { get; }
/// <summary>
/// Get companies matching provided paginated query
/// </summary>
/// <param name="searchQuery">Paginated query description</param>
/// <returns>Part of companies collection</returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IReadOnlyCollection<Company>> SearchByNameAsync([FromQuery] SearchQuery searchQuery, CancellationToken cancellationToken) =>
await Context.Companies
.Where(c => c.Name.ToLower().Contains(searchQuery.Query.ToLower()))
.OrderBy(o => o.Name)
.Skip(searchQuery.Page * searchQuery.PerPage)
.Take(searchQuery.PerPage)
.ToListAsync(cancellationToken);
/// <summary>
/// Get companies matching provided paginated query
/// </summary>
/// <param name="searchQuery">Paginated query description</param>
/// <param name="companyId"></param>
/// <response code="200">Successfully retrieved matching offices</response>
/// <response code="400">Search query was malformed</response>
/// <returns>Part of companies collection</returns>
[HttpGet("{companyId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IReadOnlyCollection<BranchOffice>> SearchBranchesByAddress([FromQuery] SearchQuery searchQuery, long companyId, CancellationToken token)
{
var company = await Context.Companies.Where(c => c.Id == companyId).FirstAsync(token);
return await Context.Entry(company)
.Collection(c => c.Branches)
.Query()
.Where(office => office.Address.City.Contains(searchQuery.Query.ToLower()))
.Skip(searchQuery.Page * searchQuery.PerPage)
.Take(searchQuery.PerPage)
.ToListAsync(token);
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Threading.Tasks;
using InternshipSystem.Api.Queries;
using InternshipSystem.Repository;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace InternshipSystem.Api.Controllers
{
public class DocumentsController : ControllerBase
{
private InternshipDbContext Context { get; }
public DocumentsController(InternshipDbContext context)
{
Context = context;
}
/// <summary>
/// Fill out required document,
/// </summary>
/// <param name="document">Documents Scan and description, and Id of filled document</param>
/// <returns></returns>
/// <response code="200">If change was successfully registered</response>
/// <response code="400">If the provided query was malformed</response>
/// <response code="404">Id doesn't match any required document</response>
/// <response code="401">This action is only available for authorized student registered for current edition</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult> AddDocumentToInternship([FromBody] DocumentPublishRequest document) =>
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
using InternshipSystem.Api.Result;
using InternshipSystem.Core;
using InternshipSystem.Repository;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace InternshipSystem.Api.Controllers
{
[Route("edition")]
public class EditionController : ControllerBase
{
private InternshipDbContext Context { get; }
public EditionController(InternshipDbContext context)
{
Context = context;
}
/// <summary>
/// Get current edition parameters
/// </summary>
/// <response code="200">Parameters of edition registered for by student</response>
/// <response code="401">This action is only available for authorized student registered for current edition</response>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<EditionResult>> GetCurrentEdition() =>
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using InternshipSystem.Api.Queries;
using InternshipSystem.Repository;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace InternshipSystem.Api.Controllers
{
[Route("internshipRegistration")]
public class InternshipRegistrationController : ControllerBase
{
private InternshipDbContext Context { get; }
public InternshipRegistrationController(InternshipDbContext context)
{
Context = context;
}
/// <summary>
/// Validate and add filled internship registration form
/// </summary>
/// <param name="registrationQuery">Internship registration data</param>
/// <response code="200">If registration form was successfully added</response>
/// <response code="400">If the provided registration query was malformed</response>
/// <response code="401">This action is only available for authorized student registered for current edition</response>
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult> SubmitRegistrationForm([FromBody] RegistrationFormQuery registrationQuery, CancellationToken cancellationToken) =>
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Threading.Tasks;
using InternshipSystem.Api.Result;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace InternshipSystem.Api.Controllers
{
[ApiController]
[Route("register")]
public class RegistrationController : ControllerBase
{
/// <summary>
/// Register student for edition using provided registration code
/// </summary>
/// <param name="registrationCode">GUID of edition </param>
/// <returns></returns>
/// <response code="200">If the student was successfully registered</response>
/// <response code="400">If the provided registration code was malformed</response>
/// <response code="404">The registration code doesn't match any open edition</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> RegisterStudentForEdition([FromBody] Guid registrationCode) =>
throw new NotImplementedException();
}
}

View File

@ -4,6 +4,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<NoWarn>$(NoWarn);1591;1573</NoWarn>
</PropertyGroup>
<ItemGroup>
@ -16,10 +17,6 @@
<PackageReference Include="IdentityServer4" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controllers" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../InternshipSystem.Core/InternshipSystem.Core.csproj" />
<ProjectReference Include="../InternshipSystem.Repository/InternshipSystem.Repository.csproj" />

View File

@ -0,0 +1,12 @@
using InternshipSystem.Core.ValueObject;
namespace InternshipSystem.Api.Queries
{
public class DocumentPublishRequest
{
public long Id { get; set; }
public string Description { get; set; }
public byte[] Scan { get; set; }
public DocumentType Type { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using InternshipSystem.Core;
using InternshipSystem.Core.Entity.Internship;
namespace InternshipSystem.Api.Queries
{
public class RegistrationFormQuery
{
public Company Company { get; set; }
public BranchOffice BranchAddress { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public InternshipType Type { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
using InternshipSystem.Core;
using InternshipSystem.Core.Entity.Internship;
namespace InternshipSystem.Api.Result
{
public struct EditionResult
{
public List<InternshipType> Types { get; set; }
public List<InternshipSubject> Subjects { get; set; }
public Student Student { get; set; }
}
}

View File

@ -1,9 +0,0 @@
namespace InternshipSystem.Core
{
public class Approval
{
public long Id { get; set; }
public byte[] Scan { get; set; }
public DocumentState State { get; set; }
}
}

View File

@ -6,7 +6,7 @@ namespace InternshipSystem.Core
public class Company
{
public long Id { get; set; }
public string Nip { get; set; }
public Nip Nip { get; set; }
public string Name { get; set; }
public RangeOfActivity Range { get; set; }
public List<BranchOffice> Branches { get; set; }

View File

@ -1,9 +1,13 @@
namespace InternshipSystem.Core
using InternshipSystem.Core.ValueObject;
namespace InternshipSystem.Core
{
public class Document
{
public long Id { get; set; }
public string Description { get; set; }
public byte[] Scan { get; set; }
public DocumentType Type { get; set; }
public DocumentState State { get; set; }
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
namespace InternshipSystem.Core
{
@ -10,7 +9,7 @@ namespace InternshipSystem.Core
public InternshipRegistration InternshipRegistration { get; set; }
public InternshipProgram InternshipProgram { get; set; }
public Report Report { get; set; }
public List<Approval> Approvals { get; set; }
public List<Document> Documents { get; set; }
public List<Document> Approvals { get; set; }
public List<Document> Documentation { get; set; }
}
}

View File

@ -2,7 +2,7 @@
{
public enum DocumentState
{
Draft,
NotSubmitted,
Submitted,
Accepted,
Rejected

View File

@ -0,0 +1,7 @@
namespace InternshipSystem.Core.ValueObject
{
public enum DocumentType
{
IPPScan
}
}

View File

@ -5,6 +5,6 @@
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public PhoneNumber PhoneNumber { get; set; }
}
}

View File

@ -0,0 +1,18 @@
namespace InternshipSystem.Core
{
public struct Nip
{
private readonly string _nip;
public Nip(string nip)
{
_nip = nip;
}
public static implicit operator string(Nip nip) =>
nip._nip;
public static implicit operator Nip(string maybeNip) =>
new Nip(maybeNip);
}
}

View File

@ -0,0 +1,18 @@
namespace InternshipSystem.Core
{
public struct PhoneNumber
{
private readonly string _phoneNumber;
public PhoneNumber(string phoneNumber)
{
_phoneNumber = phoneNumber;
}
public static implicit operator string(PhoneNumber number) =>
number._phoneNumber;
public static implicit operator PhoneNumber(string maybeNumber) =>
new PhoneNumber(maybeNumber);
}
}

View File

@ -21,11 +21,21 @@ namespace InternshipSystem.Repository
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Company>()
.Property(company => company.Nip)
.HasConversion<string>(
nip => nip,
s => (Nip)s);
modelBuilder.Entity<BranchOffice>()
.OwnsOne(bo => bo.Address);
modelBuilder.Entity<InternshipProgram>()
.OwnsOne(ip => ip.Mentor);
.OwnsOne(ip => ip.Mentor)
.Property(mentor => mentor.PhoneNumber)
.HasConversion<string>(
number => number,
s => (PhoneNumber)s);
modelBuilder.Entity<ProgramSubject>(builder =>
{