Refactored and fixed errors

This commit is contained in:
2024-08-15 23:42:18 +03:00
parent 72924fb037
commit 026a104131
21 changed files with 165 additions and 65 deletions

View File

@@ -1,7 +1,7 @@
using ApplicationLayer.Common; using ApplicationLayer.GeneralNeededServices;
using Domains.ApplicantDomain; using Domains.ApplicantDomain;
namespace ApplicationLayer.Applicants; namespace ApplicationLayer.Applicants.NeededServices;
/// Repository pattern for <see cref="Applicant"/> /// Repository pattern for <see cref="Applicant"/>
public interface IApplicantsRepository : IGenericRepository<Applicant> { } public interface IApplicantsRepository : IGenericRepository<Applicant> { }

View File

@@ -10,4 +10,8 @@
<ProjectReference Include="..\Domains\Domains.csproj" /> <ProjectReference Include="..\Domains\Domains.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0-preview.7.24405.7" />
</ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,16 @@
using ApplicationLayer.VisaApplications.Handlers;
using Microsoft.Extensions.DependencyInjection;
namespace ApplicationLayer;
/// Provides methods to add services to DI-container
public static class DependencyInjection
{
/// Add services for Application layer
public static IServiceCollection AddApplicationLayer(this IServiceCollection services)
{
services.AddScoped<IVisaApplicationsRequestHandler, VisaApplicationRequestsHandler>();
return services;
}
}

View File

@@ -1,6 +1,6 @@
using Domains; using Domains;
namespace ApplicationLayer.Common; namespace ApplicationLayer.GeneralNeededServices;
/// <summary> /// <summary>
/// Generic repository pattern /// Generic repository pattern
@@ -15,7 +15,7 @@ public interface IGenericRepository<T> where T : class, IEntity
/// Get one entity with specific id /// Get one entity with specific id
/// <param name="id">Identifier of entity</param> /// <param name="id">Identifier of entity</param>
/// <param name="cancellationToken">Cancellation token</param> /// <param name="cancellationToken">Cancellation token</param>
Task<T> GetOneAsync(Guid id, CancellationToken cancellationToken); Task<T> GetByIdAsync(Guid id, CancellationToken cancellationToken);
/// Add entity to storage /// Add entity to storage
/// <param name="entity">Entity to add</param> /// <param name="entity">Entity to add</param>

View File

@@ -1,14 +0,0 @@
using ApplicationLayer.Common;
using Domains.LocationDomain;
namespace ApplicationLayer.Locations;
public interface ICitiesRepository : IGenericRepository<City>
{
/// Find the city by its name and its country name
/// <param name="name">City's name</param>
/// <param name="countryName">City's country name</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>City with specific name and country</returns>
Task<City> GetByNameAsync(string name, string countryName, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,6 @@
using ApplicationLayer.GeneralNeededServices;
using Domains.LocationDomain;
namespace ApplicationLayer.Locations.NeededServices;
public interface ICitiesRepository : IGenericRepository<City> { }

View File

@@ -1,6 +1,6 @@
using ApplicationLayer.Common; using ApplicationLayer.GeneralNeededServices;
using Domains.LocationDomain; using Domains.LocationDomain;
namespace ApplicationLayer.Locations; namespace ApplicationLayer.Locations.NeededServices;
public interface ICountriesRepository : IGenericRepository<Country> { } public interface ICountriesRepository : IGenericRepository<Country> { }

View File

@@ -0,0 +1,11 @@
using ApplicationLayer.VisaApplications.Requests;
using Domains.VisaApplicationDomain;
namespace ApplicationLayer.VisaApplications.Handlers;
public interface IVisaApplicationsRequestHandler
{
Task<List<VisaApplication>> Get(CancellationToken cancellationToken);
void HandleCreateRequest(VisaApplicationCreateRequest request, CancellationToken cancellationToken);
}

View File

@@ -1,14 +1,78 @@
using ApplicationLayer.Applicants; using ApplicationLayer.Locations.NeededServices;
using ApplicationLayer.VisaApplications.Models;
using ApplicationLayer.VisaApplications.NeededServices;
using ApplicationLayer.VisaApplications.Requests; using ApplicationLayer.VisaApplications.Requests;
using Domains.ApplicantDomain;
using Domains.VisaApplicationDomain;
namespace ApplicationLayer.VisaApplications.Handlers namespace ApplicationLayer.VisaApplications.Handlers;
/// Handles visa requests
public class VisaApplicationRequestsHandler(
IVisaApplicationsRepository applications,
ICitiesRepository cities,
ICountriesRepository countries) : IVisaApplicationsRequestHandler
{ {
/// Handles visa requests public async Task<List<VisaApplication>> Get(CancellationToken cancellationToken) => await applications.GetAllAsync(cancellationToken);
public class VisaApplicationRequestsHandler(IApplicantsRepository)
{
public void HandleCreateRequest(CreateVisaApplicationRequest request)
{
} public async void HandleCreateRequest(VisaApplicationCreateRequest request, CancellationToken cancellationToken)
{
//TODO mapper
var cityOfBirth = await cities.GetByIdAsync(request.BirthCityId, cancellationToken);
var cityOfWork = await cities.GetByIdAsync(request.PlaceOfWork.Address.CityId, cancellationToken);
var addressOfWork = new Address
{
City = cityOfWork,
Country = cityOfWork.Country,
Building = request.PlaceOfWork.Address.Building,
Street = request.PlaceOfWork.Address.Street
};
var applicant = new Applicant
{
MaritalStatus = request.MaritalStatus,
Name = request.FullName,
Passport = request.Passport,
Gender = request.Gender,
Citizenship = request.CitizenShip,
BirthDate = request.BirthDate,
FatherName = request.FatherName,
JobTitle = request.JobTitle,
MotherName = request.MotherName,
CitizenshipByBirth = request.CitizenshipByBirth,
CityOfBirth = cityOfBirth,
CountryOfBirth = cityOfBirth.Country,
IsNonResident = request.IsNonResident,
PlaceOfWork = new PlaceOfWork { Address = addressOfWork, Name = request.PlaceOfWork.Name, PhoneNum = request.PlaceOfWork.PhoneNum }
};
var pastVisits = request.PastVisits.Select(m => ConvertPastVisitModelToPastVisit(m, cancellationToken).Result).ToList();
var visaApplication = new VisaApplication
{
Applicant = applicant,
RequestedNumberOfEntries = request.RequestedNumberOfEntries,
ValidDaysRequested = request.ValidDaysRequested,
ReentryPermit = request.ReentryPermit,
VisaCategory = request.VisaCategory,
PermissionToDestCountry = request.PermissionToDestCountry,
DestinationCountry = await countries.GetByIdAsync(request.DestinationCountryId, cancellationToken),
PastVisas = request.PastVisas.ToList(),
PastVisits = pastVisits,
ForGroup = request.IsForGroup,
RequestDate = DateTime.Today
};
await applications.AddAsync(visaApplication, cancellationToken);
}
private async Task<PastVisit> ConvertPastVisitModelToPastVisit(PastVisitModel model, CancellationToken cancellationToken)
{
return new PastVisit
{
DestinationCountry = await countries.GetByIdAsync(model.DestinationCountryId, cancellationToken),
StartDate = model.StartDate,
EndDate = model.EndDate
};
} }
} }

View File

@@ -1,6 +0,0 @@
using ApplicationLayer.Common;
using Domains.VisaApplicationDomain;
namespace ApplicationLayer.VisaApplications;
public interface IVisaApplicationsRepository : IGenericRepository<VisaApplication> { }

View File

@@ -2,11 +2,8 @@
public class AddressModel public class AddressModel
{ {
/// Country part of address
public string Country { get; set; } = null!;
/// City part of address /// City part of address
public string City { get; set; } = null!; public Guid CityId { get; set; }
/// Street part of address /// Street part of address
public string Street { get; set; } = null!; public string Street { get; set; } = null!;

View File

@@ -0,0 +1,14 @@
namespace ApplicationLayer.VisaApplications.Models
{
public class PastVisitModel
{
/// First day of <see cref="PastVisitModel"/>
public DateTime StartDate { get; set; }
/// Last day of <see cref="PastVisitModel"/>
public DateTime EndDate { get; set; }
/// Identifier of destination country of <see cref="PastVisitModel"/>
public Guid DestinationCountryId { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
using ApplicationLayer.GeneralNeededServices;
using Domains.VisaApplicationDomain;
namespace ApplicationLayer.VisaApplications.NeededServices;
public interface IVisaApplicationsRepository : IGenericRepository<VisaApplication> { }

View File

@@ -5,12 +5,11 @@ using Domains.VisaApplicationDomain;
namespace ApplicationLayer.VisaApplications.Requests; namespace ApplicationLayer.VisaApplications.Requests;
/// Model of visa request from user /// Model of visa request from user
public record CreateVisaApplicationRequest( public record VisaApplicationCreateRequest(
Name FullName, Name FullName,
Passport Passport, Passport Passport,
DateTime BirthDate, DateTime BirthDate,
string BirthCity, Guid BirthCityId,
string BirthCountry,
string CitizenShip, string CitizenShip,
string CitizenshipByBirth, string CitizenshipByBirth,
Gender Gender, Gender Gender,
@@ -21,12 +20,12 @@ public record CreateVisaApplicationRequest(
ReentryPermit ReentryPermit, ReentryPermit ReentryPermit,
string JobTitle, string JobTitle,
PlaceOfWorkModel PlaceOfWork, PlaceOfWorkModel PlaceOfWork,
string DestinationCountry, Guid DestinationCountryId,
VisaCategory VisaCategory, VisaCategory VisaCategory,
bool IsForGroup, bool IsForGroup,
RequestedNumberOfEntries RequestedNumberOfEntries, RequestedNumberOfEntries RequestedNumberOfEntries,
int ValidDaysRequested, int ValidDaysRequested,
PastVisa[] PastVisas, PastVisa[] PastVisas,
PermissionToDestCountry? PermissionToDestCountry, PermissionToDestCountry? PermissionToDestCountry,
PastVisit[] PastVisits PastVisitModel[] PastVisits
); );

View File

@@ -1,5 +1,4 @@
using Domains.LocationDomain; using Domains.LocationDomain;
using Domains.VisaApplicationDomain;
namespace Domains.ApplicantDomain; namespace Domains.ApplicantDomain;
@@ -50,7 +49,4 @@ public class Applicant : IEntity
/// Is <see cref="Applicant"/> a non-resident /// Is <see cref="Applicant"/> a non-resident
public bool IsNonResident { get; set; } public bool IsNonResident { get; set; }
}
/// List of <see cref="Applicant"/>'s applications
public List<VisaApplication> VisaApplications { get; set; } = null!;
}

View File

@@ -9,4 +9,4 @@ public class Name
public string Surname { get; set; } = null!; public string Surname { get; set; } = null!;
public string? Patronymic { get; set; } public string? Patronymic { get; set; }
} }

View File

@@ -1,4 +1,5 @@
using Domains.ApplicantDomain; using Domains.ApplicantDomain;
using Domains.LocationDomain;
namespace Domains.VisaApplicationDomain; namespace Domains.VisaApplicationDomain;
@@ -11,4 +12,7 @@ public class PastVisit
/// Last day of <see cref="PastVisit"/> /// Last day of <see cref="PastVisit"/>
public DateTime EndDate { get; set; } public DateTime EndDate { get; set; }
/// Destination country of <see cref="PastVisit"/>
public Country DestinationCountry { get; set; } = null!;
} }

View File

@@ -1,6 +1,6 @@
using ApplicationLayer.Applicants; using ApplicationLayer.Applicants.NeededServices;
using ApplicationLayer.Locations; using ApplicationLayer.Locations.NeededServices;
using ApplicationLayer.VisaApplications; using ApplicationLayer.VisaApplications.NeededServices;
using Infrastructure.Database; using Infrastructure.Database;
using Infrastructure.Database.Applicants.Repositories; using Infrastructure.Database.Applicants.Repositories;
using Infrastructure.Database.Generic; using Infrastructure.Database.Generic;
@@ -20,7 +20,7 @@ public static class DependencyInjection
public static IServiceCollection AddInfrastructure(this IServiceCollection services) public static IServiceCollection AddInfrastructure(this IServiceCollection services)
{ {
//TODO строка подключения //TODO строка подключения
services.AddDbContext<DbContext>(opts => services.AddDbContextFactory<DbContext>(opts =>
opts.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=visadb;Integrated Security=True;")); opts.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=visadb;Integrated Security=True;"));
services.AddScoped<IGenericReader>(serviceProvider => serviceProvider.GetRequiredService<DbContext>()); services.AddScoped<IGenericReader>(serviceProvider => serviceProvider.GetRequiredService<DbContext>());
@@ -34,4 +34,4 @@ public static class DependencyInjection
return services; return services;
} }
} }

View File

@@ -1,3 +1,4 @@
using ApplicationLayer.VisaApplications.Handlers;
using ApplicationLayer.VisaApplications.Requests; using ApplicationLayer.VisaApplications.Requests;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -5,17 +6,18 @@ namespace SchengenVisaApi.Controllers;
[ApiController] [ApiController]
[Route("[controller]")] [Route("[controller]")]
public class VisaApplicationController : ControllerBase public class VisaApplicationController(IVisaApplicationsRequestHandler visaApplicationsRequestHandler) : ControllerBase
{ {
[HttpGet]
public VisaApplicationController() public async Task<IActionResult> Get(CancellationToken cancellationToken)
{ {
var result = await visaApplicationsRequestHandler.Get(cancellationToken);
} return Ok(result);
}
[HttpPost] [HttpPost]
public void Create(CreateVisaApplicationRequest request) public void Create(VisaApplicationCreateRequest request, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); visaApplicationsRequestHandler.HandleCreateRequest(request, cancellationToken);
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Reflection; using System.Reflection;
using ApplicationLayer;
using Infrastructure; using Infrastructure;
namespace SchengenVisaApi; namespace SchengenVisaApi;
@@ -11,6 +12,7 @@ public static class DependencyInjection
{ {
services services
.AddInfrastructure() .AddInfrastructure()
.AddApplicationLayer()
.AddPresentation(); .AddPresentation();
return services; return services;
@@ -27,4 +29,4 @@ public static class DependencyInjection
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
}); });
} }
} }

View File

@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>