Вытащил солюшен на уровень выше, чтобы прощё было дотнетить
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-10-05 14:32:06 +03:00
parent fa87a56ad1
commit aae4b28089
242 changed files with 159 additions and 159 deletions

View File

@@ -0,0 +1,22 @@
using System.IdentityModel.Tokens.Jwt;
using ApplicationLayer.InfrastructureServicesInterfaces;
using Microsoft.Extensions.DependencyInjection;
namespace Infrastructure.Auth;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddTokenGenerator(this IServiceCollection services, TokenGeneratorOptions options)
{
services.AddSingleton<JwtSecurityTokenHandler>();
services.AddSingleton<ITokenGenerator, TokenGenerator>(provider =>
{
var tokenHandler = provider.GetRequiredService<JwtSecurityTokenHandler>();
var dateTimeProvider = provider.GetRequiredService<IDateTimeProvider>();
return new TokenGenerator(options, tokenHandler, dateTimeProvider);
});
return services;
}
}

View File

@@ -0,0 +1,34 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using ApplicationLayer.InfrastructureServicesInterfaces;
using ApplicationLayer.Services.AuthServices.Common;
using Domains.Users;
namespace Infrastructure.Auth;
/// <inheritdoc cref="ITokenGenerator"/>
/// <param name="options">options kind of one in authorization registration in DI methods</param>
/// <param name="tokenHandler">token handler</param>
/// <param name="dateTimeProvider">date time provider</param>
public class TokenGenerator(TokenGeneratorOptions options, JwtSecurityTokenHandler tokenHandler, IDateTimeProvider dateTimeProvider)
: ITokenGenerator
{
/// <inheritdoc cref="ITokenGenerator.CreateToken"/>
public AuthToken CreateToken(User user)
{
var claims = new List<Claim>
{
new(ClaimTypes.Role, user.Role.ToString()),
new(ClaimTypes.NameIdentifier, user.Id.ToString())
};
var token = new JwtSecurityToken(
issuer: options.Issuer,
audience: options.Audience,
expires: dateTimeProvider.Now().Add(options.ValidTime),
signingCredentials: options.Credentials,
claims: claims);
return new AuthToken { Token = tokenHandler.WriteToken(token) };
}
}

View File

@@ -0,0 +1,5 @@
using Microsoft.IdentityModel.Tokens;
namespace Infrastructure.Auth;
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);

View File

@@ -0,0 +1,22 @@
using ApplicationLayer.Services.Applicants.Models;
using ApplicationLayer.Services.AuthServices.Requests;
using AutoMapper;
using Domains.ApplicantDomain;
namespace Infrastructure.Automapper.Profiles;
public class ApplicantProfile : Profile
{
public ApplicantProfile()
{
CreateMap<Applicant, ApplicantModel>(MemberList.Destination).ReverseMap();
CreateMap<RegisterApplicantRequest, Applicant>(MemberList.Destination)
.ForMember(a => a.UserId, opts => opts.Ignore())
.ForMember(a => a.Name,
opts => opts.MapFrom(r => r.ApplicantName));
CreateMap<NameModel, Name>().ReverseMap();
CreateMap<PassportModel, Passport>().ReverseMap();
}
}

View File

@@ -0,0 +1,18 @@
using ApplicationLayer.Services.Applicants.Models;
using AutoMapper;
using Domains.ApplicantDomain;
namespace Infrastructure.Automapper.Profiles;
public class PlaceOfWorkProfile : Profile
{
public PlaceOfWorkProfile()
{
CreateMap<PlaceOfWorkModel, PlaceOfWork>(MemberList.Destination)
.ForMember(p => p.Id,
opts => opts.UseDestinationValue())
.ReverseMap();
CreateMap<AddressModel, Address>().ReverseMap();
}
}

View File

@@ -0,0 +1,18 @@
using ApplicationLayer.Services.AuthServices.Common;
using ApplicationLayer.Services.Users.Models;
using AutoMapper;
using Domains.Users;
namespace Infrastructure.Automapper.Profiles;
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<AuthData, User>(MemberList.Destination)
.ForMember(u => u.Role,
opts => opts.Ignore());
CreateMap<User, UserModel>(MemberList.Destination);
}
}

View File

@@ -0,0 +1,29 @@
using ApplicationLayer.Services.VisaApplications.Models;
using ApplicationLayer.Services.VisaApplications.Requests;
using AutoMapper;
using Domains.VisaApplicationDomain;
namespace Infrastructure.Automapper.Profiles;
public class VisaApplicationProfile : Profile
{
public VisaApplicationProfile()
{
CreateMap<VisaApplication, VisaApplicationPreview>(MemberList.Destination);
CreateMap<VisaApplication, VisaApplicationModel>(MemberList.Destination)
.ForMember(model => model.Applicant,
opts => opts.Ignore());
CreateMap<VisaApplicationCreateRequest, VisaApplication>(MemberList.Destination)
.ForMember(va => va.RequestDate,
opts => opts.Ignore())
.ForMember(va => va.ApplicantId,
opts => opts.Ignore());
CreateMap<PastVisaModel, PastVisa>().ReverseMap();
CreateMap<PastVisitModel, PastVisit>().ReverseMap();
CreateMap<ReentryPermitModel, ReentryPermit>().ReverseMap();
CreateMap<PermissionToDestCountryModel, PermissionToDestCountry>().ReverseMap();
}
}

View File

@@ -0,0 +1,9 @@
using ApplicationLayer.InfrastructureServicesInterfaces;
namespace Infrastructure.Common;
/// Implements <see cref="IDateTimeProvider"/>
public class DateTimeProvider : IDateTimeProvider
{
DateTime IDateTimeProvider.Now() => DateTime.Now;
}

View File

@@ -0,0 +1,18 @@
using System.Security.Claims;
using ApplicationLayer.InfrastructureServicesInterfaces;
using Microsoft.AspNetCore.Http;
namespace Infrastructure.Common;
public class UserIdProvider(IHttpContextAccessor contextAccessor) : IUserIdProvider
{
Guid IUserIdProvider.GetUserId()
{
var claim = contextAccessor.HttpContext!.User.Claims.SingleOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier);
if (claim is null)
{
throw new InvalidOperationException("UserIdProvider call for request with no authorization");
}
return Guid.Parse(claim.Value);
}
}

View File

@@ -0,0 +1,27 @@
using Domains;
using Domains.ApplicantDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Applicants.Configuration;
public static class AddressConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, Address> entity)
{
entity.Property(a => a.Country)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
entity.Property(a => a.City)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CityNameLength);
entity.Property(a => a.Street)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.StreetNameLength);
entity.Property(a => a.Building)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.BuildingNumberLength);
}
}

View File

@@ -0,0 +1,40 @@
using Domains;
using Domains.ApplicantDomain;
using Domains.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Applicants.Configuration;
public class ApplicantConfiguration : IEntityTypeConfiguration<Applicant>
{
public void Configure(EntityTypeBuilder<Applicant> entity)
{
entity.OwnsOne(a => a.Name, NameConfiguration<Applicant>.Configure);
entity.OwnsOne(a => a.FatherName, NameConfiguration<Applicant>.Configure);
entity.OwnsOne(a => a.MotherName, NameConfiguration<Applicant>.Configure);
entity.OwnsOne(a => a.Passport, PassportConfiguration<Applicant>.Configure);
entity.HasOne<User>().WithOne().HasForeignKey<Applicant>(a => a.UserId);
entity.Property(a => a.Citizenship)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CitizenshipLength);
entity.Property(a => a.CitizenshipByBirth)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CitizenshipLength);
entity.Property(a => a.CountryOfBirth)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
entity.Property(a => a.CityOfBirth)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CityNameLength);
entity.Property(a => a.JobTitle)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.JobTitleLength);
}
}

View File

@@ -0,0 +1,23 @@
using Domains;
using Domains.ApplicantDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Applicants.Configuration;
public static class NameConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, Name> entity)
{
entity.Property(p => p.FirstName)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.NameLength);
entity.Property(p => p.Surname)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.NameLength);
entity.Property(p => p.Patronymic)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.NameLength);
}
}

View File

@@ -0,0 +1,19 @@
using Domains;
using Domains.ApplicantDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Applicants.Configuration;
public static class PassportConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, Passport> entity)
{
entity.Property(p => p.Number)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.PassportNumberLength);
entity.Property(p => p.Issuer)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.IssuerNameLength);
}
}

View File

@@ -0,0 +1,22 @@
using Domains;
using Domains.ApplicantDomain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Applicants.Configuration;
public class PlaceOfWorkConfiguration : IEntityTypeConfiguration<PlaceOfWork>
{
public void Configure(EntityTypeBuilder<PlaceOfWork> entity)
{
entity.OwnsOne(p => p.Address, AddressConfiguration<PlaceOfWork>.Configure);
entity.Property(p => p.Name)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.PlaceOfWorkNameLength);
entity.Property(p => p.PhoneNum)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.PhoneNumberLength);
}
}

View File

@@ -0,0 +1,39 @@
using ApplicationLayer.Services.Applicants.NeededServices;
using Domains.ApplicantDomain;
using Infrastructure.Database.Applicants.Repositories.Exceptions;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.Applicants.Repositories;
/// Repository pattern for <see cref="Applicant"/>
/// <param name="reader"><inheritdoc cref="IGenericReader"/></param>
/// <param name="writer"><inheritdoc cref="IGenericWriter"/></param>
public sealed class ApplicantsRepository(IGenericReader reader, IGenericWriter writer)
: GenericRepository<Applicant>(reader, writer), IApplicantsRepository
{
protected override IQueryable<Applicant> LoadDomain()
{
return base.LoadDomain()
.Include(a => a.PlaceOfWork);
}
/// <inheritdoc cref="IApplicantsRepository.FindByUserIdAsync"/>
public async Task<Applicant> FindByUserIdAsync(Guid userId, CancellationToken cancellationToken)
{
var result = await LoadDomain().SingleOrDefaultAsync(a => a.UserId == userId, cancellationToken);
return result ?? throw new ApplicantNotFoundByUserIdException();
}
async Task<Guid> IApplicantsRepository.GetApplicantIdByUserId(Guid userId, CancellationToken cancellationToken)
{
var result = await base.LoadDomain().SingleOrDefaultAsync(a => a.UserId == userId, cancellationToken);
return result?.Id ?? throw new ApplicantNotFoundByUserIdException();
}
async Task<bool> IApplicantsRepository.IsApplicantNonResidentByUserId(Guid userId, CancellationToken cancellationToken)
{
var applicant = await FindByUserIdAsync(userId, cancellationToken);
return applicant.IsNonResident;
}
}

View File

@@ -0,0 +1,5 @@
using ApplicationLayer.GeneralExceptions;
namespace Infrastructure.Database.Applicants.Repositories.Exceptions;
public class ApplicantNotFoundByUserIdException() : EntityNotFoundException("Applicant not found.");

View File

@@ -0,0 +1,39 @@
using System.Reflection;
using ApplicationLayer.InfrastructureServicesInterfaces;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database;
public class DatabaseContext(DbContextOptions<DatabaseContext> opts) : DbContext(opts), IGenericWriter, IGenericReader, IUnitOfWork
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
async Task IGenericWriter.AddAsync<T>(T entity, CancellationToken cancellationToken)
{
await AddAsync(entity, cancellationToken);
}
void IGenericWriter.Update<T>(T entity)
{
Update(entity);
}
void IGenericWriter.Remove<T>(T entity)
{
Remove(entity);
}
IQueryable<T> IGenericReader.GetAll<T>()
{
return Set<T>();
}
async Task IUnitOfWork.SaveAsync(CancellationToken cancellationToken)
{
await SaveChangesAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,48 @@
using ApplicationLayer.GeneralExceptions;
using ApplicationLayer.InfrastructureServicesInterfaces;
using Domains;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.Generic;
/// Generic repository pattern
/// <param name="writer"><inheritdoc cref="IGenericWriter"/></param>
/// <typeparam name="T">Type of entity</typeparam>
/// <remarks>Should be inherited to create typed repositories</remarks>
public abstract class GenericRepository<T>(IGenericReader reader, IGenericWriter writer) : IGenericRepository<T>
where T : class, IEntity
{
/// <inheritdoc cref="IGenericRepository{T}.GetAllAsync"/>
public async Task<List<T>> GetAllAsync(CancellationToken cancellationToken)
=> await LoadDomain().ToListAsync(cancellationToken);
/// <inheritdoc cref="IGenericRepository{T}.GetByIdAsync"/>
public async Task<T> GetByIdAsync(Guid id, CancellationToken cancellationToken)
{
var result = await LoadDomain().SingleOrDefaultAsync(a => a.Id == id, cancellationToken);
return result ?? throw new EntityNotFoundByIdException<T>(id);
}
/// <inheritdoc cref="IGenericRepository{T}.AddAsync"/>
public async Task AddAsync(T entity, CancellationToken cancellationToken)
=> await writer.AddAsync(entity, cancellationToken);
/// <inheritdoc cref="IGenericRepository{T}.UpdateAsync"/>
public async Task UpdateAsync(T entity, CancellationToken cancellationToken)
{
await GetByIdAsync(entity.Id, cancellationToken);
writer.Update(entity);
}
/// <inheritdoc cref="IGenericRepository{T}.Remove"/>
public void Remove(T entity)
{
writer.Remove(entity);
}
/// Should be overriden to load navigation properties of entity
protected virtual IQueryable<T> LoadDomain()
{
return reader.GetAll<T>();
}
}

View File

@@ -0,0 +1,11 @@
using Domains;
namespace Infrastructure.Database.Generic;
/// Reads from data storage
public interface IGenericReader
{
/// Get all entities of type T stored in storage
/// <typeparam name="T">Entity type to seek in storage</typeparam>
IQueryable<T> GetAll<T>() where T : class, IEntity;
}

View File

@@ -0,0 +1,25 @@
using ApplicationLayer.InfrastructureServicesInterfaces;
using Domains;
namespace Infrastructure.Database.Generic;
/// Writes data to data storage
/// <remarks><see cref="IUnitOfWork"/> should be used to save changes</remarks>
public interface IGenericWriter
{
/// Add entity to data storage
/// <param name="entity">Entity to add</param>
/// <param name="cancellationToken">Cancellation Token</param>
/// <typeparam name="T">Entity type</typeparam>
Task AddAsync<T>(T entity, CancellationToken cancellationToken) where T : class, IEntity;
/// Update entity in data storage
/// <param name="entity">Entity to update</param>
/// <typeparam name="T">Entity type</typeparam>
void Update<T>(T entity) where T : class, IEntity;
/// Remove entity from data storage
/// <param name="entity">Entity to remove</param>
/// <typeparam name="T">Entity type</typeparam>
void Remove<T>(T entity) where T : class, IEntity;
}

View File

@@ -0,0 +1,22 @@
using Domains;
using Domains.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Users.Configuration;
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> entity)
{
entity.Property(u => u.Email)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.EmailLength);
entity.HasIndex(u => u.Email).IsUnique();
entity.Property(u => u.Password)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.PasswordLength);
}
}

View File

@@ -0,0 +1,21 @@
using ApplicationLayer.Services.AuthServices.NeededServices;
using Domains.Users;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.Users.Repositories;
/// <inheritdoc cref="IUsersRepository"/>
public class UsersRepository(IGenericReader reader, IGenericWriter writer)
: GenericRepository<User>(reader, writer), IUsersRepository
{
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken cancellationToken)
{
return await LoadDomain().SingleOrDefaultAsync(u => u.Email == email, cancellationToken);
}
async Task<List<User>> IUsersRepository.GetAllOfRoleAsync(Role role, CancellationToken cancellationToken)
{
return await LoadDomain().Where(u => u.Role == role).ToListAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,15 @@
using Domains;
using Domains.VisaApplicationDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.VisaApplications.Configuration;
public static class PastVisaConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, PastVisa> entity)
{
entity.Property(p => p.Name)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.VisaNameLength);
}
}

View File

@@ -0,0 +1,15 @@
using Domains;
using Domains.VisaApplicationDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.VisaApplications.Configuration;
public static class PastVisitConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, PastVisit> entity)
{
entity.Property(pv => pv.DestinationCountry)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
}
}

View File

@@ -0,0 +1,15 @@
using Domains;
using Domains.VisaApplicationDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.VisaApplications.Configuration;
public static class PermissionToDestCountryConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, PermissionToDestCountry> entity)
{
entity.Property(p => p.Issuer)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.IssuerNameLength);
}
}

View File

@@ -0,0 +1,15 @@
using Domains;
using Domains.VisaApplicationDomain;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.VisaApplications.Configuration;
public static class ReentryPermitConfiguration<T> where T : class, IEntity
{
public static void Configure(OwnedNavigationBuilder<T, ReentryPermit> entity)
{
entity.Property(p => p.Number)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.ReentryPermitNumberLength);
}
}

View File

@@ -0,0 +1,27 @@
using Domains;
using Domains.ApplicantDomain;
using Domains.VisaApplicationDomain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.VisaApplications.Configuration;
public class VisaApplicationConfiguration : IEntityTypeConfiguration<VisaApplication>
{
public void Configure(EntityTypeBuilder<VisaApplication> entity)
{
entity.OwnsOne(va => va.ReentryPermit, ReentryPermitConfiguration<VisaApplication>.Configure);
entity.OwnsOne(va => va.PermissionToDestCountry, PermissionToDestCountryConfiguration<VisaApplication>.Configure);
entity.OwnsMany(va => va.PastVisits, PastVisitConfiguration<VisaApplication>.Configure);
entity.OwnsMany(va => va.PastVisas, PastVisaConfiguration<VisaApplication>.Configure);
entity.Property(va => va.DestinationCountry)
.IsUnicode(false)
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
entity.HasOne<Applicant>()
.WithMany()
.HasForeignKey(va => va.ApplicantId)
.IsRequired();
}
}

View File

@@ -0,0 +1,6 @@
using ApplicationLayer.GeneralExceptions;
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions;
public class ApplicationNotFoundByApplicantAndApplicationIdException(Guid applicationId)
: EntityNotFoundException($"Application with id {applicationId} not found for authenticated user");

View File

@@ -0,0 +1,36 @@
using ApplicationLayer.Services.VisaApplications.NeededServices;
using Domains.VisaApplicationDomain;
using Infrastructure.Database.Generic;
using Infrastructure.Database.VisaApplications.Repositories.Exceptions;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.VisaApplications.Repositories;
public sealed class VisaApplicationsRepository(IGenericReader reader, IGenericWriter writer)
: GenericRepository<VisaApplication>(reader, writer), IVisaApplicationsRepository
{
protected override IQueryable<VisaApplication> LoadDomain()
=> base.LoadDomain()
.Include(va => va.PastVisas)
.Include(va => va.PastVisits);
async Task<List<VisaApplication>> IVisaApplicationsRepository.GetOfApplicantAsync(Guid applicantId, CancellationToken cancellationToken)
=> await LoadDomain().Where(va => va.ApplicantId == applicantId).ToListAsync(cancellationToken);
async Task<VisaApplication> IVisaApplicationsRepository.GetByApplicantAndApplicationIdAsync(
Guid applicantId,
Guid applicationId,
CancellationToken cancellationToken)
{
var result = await LoadDomain()
.SingleOrDefaultAsync(va => va.Id == applicationId && va.ApplicantId == applicantId, cancellationToken);
return result ?? throw new ApplicationNotFoundByApplicantAndApplicationIdException(applicationId);
}
async Task<List<VisaApplication>> IVisaApplicationsRepository.GetPendingApplicationsAsync(CancellationToken cancellationToken)
{
var result = LoadDomain().Where(va => va.Status == ApplicationStatus.Pending);
return await result.ToListAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,48 @@
using System.Reflection;
using ApplicationLayer.InfrastructureServicesInterfaces;
using ApplicationLayer.Services.Applicants.NeededServices;
using ApplicationLayer.Services.AuthServices.NeededServices;
using ApplicationLayer.Services.VisaApplications.NeededServices;
using Infrastructure.Common;
using Infrastructure.Database;
using Infrastructure.Database.Applicants.Repositories;
using Infrastructure.Database.Generic;
using Infrastructure.Database.Users.Repositories;
using Infrastructure.Database.VisaApplications.Repositories;
using Infrastructure.EntityToExcelTemplateWriter;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Infrastructure;
/// Provides methods to add services to DI-container
public static class DependencyInjection
{
/// Add services needed for Infrastructure layer
public static IServiceCollection AddInfrastructure(this IServiceCollection services,
IConfigurationManager configurationManager)
{
services.AddDbContext<DatabaseContext>(opts =>
opts.UseNpgsql(configurationManager.GetConnectionString("connectionString")));
services.AddScoped<IGenericReader>(serviceProvider => serviceProvider.GetRequiredService<DatabaseContext>());
services.AddScoped<IGenericWriter>(serviceProvider => serviceProvider.GetRequiredService<DatabaseContext>());
services.AddScoped<IUnitOfWork>(serviceProvider => serviceProvider.GetRequiredService<DatabaseContext>());
services.AddScoped<IApplicantsRepository, ApplicantsRepository>();
services.AddScoped<IVisaApplicationsRepository, VisaApplicationsRepository>();
services.AddScoped<IUsersRepository, UsersRepository>();
services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
services.AddSingleton<IEntityWriter, ExcelWriter>();
services.AddHttpContextAccessor();
services.AddScoped<IUserIdProvider, UserIdProvider>();
services.AddAutoMapper(Assembly.GetExecutingAssembly());
return services;
}
}

View File

@@ -0,0 +1,130 @@
using System.Reflection;
using System.Text;
using ApplicationLayer.Services.VisaApplications.NeededServices;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace Infrastructure.EntityToExcelTemplateWriter
{
/// <summary>
/// Writes object to excel using template.xlsx file and reflections
/// </summary>
public class ExcelWriter : IEntityWriter
{
private const char InsertionSymbol = '$';
private readonly char[] endChars = [',', ';'];
/// <summary>
/// Write object to stream in Excel table format
/// </summary>
/// <param name="entity"> object to write </param>
/// <param name="cancellationToken"> cancellation token </param>
/// <returns> Stream with template.xlsx file with replaced entries like '$EntityPropName.AnotherProp' </returns>
/// <exception cref="NullReferenceException"> thrown when template file is incorrect </exception>
/// <exception cref="InvalidOperationException"> thrown if any property path in template is incorrect</exception>
public async Task<Stream> WriteEntityToStream(object entity, CancellationToken cancellationToken)
{
var outStream = new MemoryStream();
await using (var stream = File.Open("template.xlsx", FileMode.Open, FileAccess.Read))
{
await stream.CopyToAsync(outStream, cancellationToken);
}
using var spreadsheetDocument = SpreadsheetDocument.Open(outStream, true);
var workbookPart = spreadsheetDocument.WorkbookPart
?? throw new NullReferenceException("There is no workbook part in document");
var shareStringTable = workbookPart.SharedStringTablePart?.SharedStringTable ??
throw new NullReferenceException("There is no data in document");
var shareStringTableItems = shareStringTable.Elements<SharedStringItem>().ToArray();
foreach (var item in shareStringTableItems)
{
if (string.IsNullOrEmpty(item.InnerText))
{
continue;
}
var entries = item.InnerText.Split();
for (var i = 0; i < entries.Length; i++)
{
var entry = entries[i];
if (entry.FirstOrDefault() is not InsertionSymbol || entry.Length <= 1)
{
continue;
}
entry = entry[1..];
var trimmedCount = entry.Length - entry.TrimEnd(endChars).Length;
var trimmed = entry[^trimmedCount..];
entry = entry.TrimEnd(endChars);
var memberPath = entry.Split('.');
var value = GetValueFor(entity, memberPath.First());
var stringToInsert = "None";
foreach (var memberName in memberPath.Skip(1))
{
if (value is null)
{
break;
}
value = GetValueFor(value, memberName);
}
if (value is not null)
{
switch (value)
{
case DateTime date:
stringToInsert = date.ToShortDateString();
break;
case Enum val:
var enumString = val.ToString();
var stringBuilder = new StringBuilder();
for (var charIndex = 0; charIndex < enumString.Length - 1; charIndex++)
{
stringBuilder.Append(enumString[charIndex]);
if (char.IsUpper(enumString[charIndex + 1]))
{
stringBuilder.Append(' ');
}
}
stringBuilder.Append(enumString.Last());
stringToInsert = stringBuilder.ToString();
break;
default:
stringToInsert = value.ToString();
break;
}
}
entries[i] = stringToInsert! + trimmed;
}
item.Text!.Text = string.Join(' ', entries);
}
spreadsheetDocument.Save();
return outStream;
}
private static object? GetValueFor(object entity, string member)
{
var memberInfo = entity.GetType()
.GetMembers()
.FirstOrDefault(p => p.Name == member)
?? throw new InvalidOperationException(
$"Invalid member path in document. Not found: {member}");
return memberInfo switch
{
PropertyInfo propertyInfo => propertyInfo.GetValue(entity),
MethodInfo methodInfo => methodInfo.Invoke(entity, []),
_ => throw new InvalidOperationException("Only properties and methods allowed.")
};
}
}
}

View File

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ApplicationLayer\ApplicationLayer.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,502 @@
// <auto-generated />
using System;
using Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Infrastructure.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20250305064153_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Citizenship")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CitizenshipByBirth")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CityOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<string>("CountryOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<bool>("IsNonResident")
.HasColumnType("boolean");
b.Property<string>("JobTitle")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("MaritalStatus")
.HasColumnType("integer");
b.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PlaceOfWorkId");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("Applicant");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b.Property<string>("PhoneNum")
.IsRequired()
.HasMaxLength(13)
.IsUnicode(false)
.HasColumnType("character varying(13)");
b.HasKey("Id");
b.ToTable("PlaceOfWork");
});
modelBuilder.Entity("Domains.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(254)
.IsUnicode(false)
.HasColumnType("character varying(254)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("User");
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<bool>("ForGroup")
.HasColumnType("boolean");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp with time zone");
b.Property<int>("RequestedNumberOfEntries")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<int>("ValidDaysRequested")
.HasColumnType("integer");
b.Property<int>("VisaCategory")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ApplicantId");
b.ToTable("VisaApplication");
});
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.HasOne("Domains.ApplicantDomain.PlaceOfWork", "PlaceOfWork")
.WithMany()
.HasForeignKey("PlaceOfWorkId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Domains.Users.User", null)
.WithOne()
.HasForeignKey("Domains.ApplicantDomain.Applicant", "UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsOne("Domains.ApplicantDomain.Name", "FatherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "MotherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "Name", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Passport", "Passport", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(20)
.IsUnicode(false)
.HasColumnType("character varying(20)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.Navigation("FatherName")
.IsRequired();
b.Navigation("MotherName")
.IsRequired();
b.Navigation("Name")
.IsRequired();
b.Navigation("Passport")
.IsRequired();
b.Navigation("PlaceOfWork");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.OwnsOne("Domains.ApplicantDomain.Address", "Address", b1 =>
{
b1.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b1.Property<string>("Building")
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false)
.HasColumnType("character varying(10)");
b1.Property<string>("City")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Country")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Street")
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false)
.HasColumnType("character varying(100)");
b1.HasKey("PlaceOfWorkId");
b1.ToTable("PlaceOfWork");
b1.WithOwner()
.HasForeignKey("PlaceOfWorkId");
});
b.Navigation("Address")
.IsRequired();
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.HasOne("Domains.ApplicantDomain.Applicant", null)
.WithMany()
.HasForeignKey("ApplicantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsMany("Domains.VisaApplicationDomain.PastVisa", "PastVisas", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Name")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisa");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsMany("Domains.VisaApplicationDomain.PastVisit", "PastVisits", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<DateTime>("EndDate")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("StartDate")
.HasColumnType("timestamp with time zone");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisit");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.PermissionToDestCountry", "PermissionToDestCountry", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.ReentryPermit", "ReentryPermit", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(25)
.IsUnicode(false)
.HasColumnType("character varying(25)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.Navigation("PastVisas");
b.Navigation("PastVisits");
b.Navigation("PermissionToDestCountry");
b.Navigation("ReentryPermit");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,211 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Infrastructure.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "PlaceOfWork",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(200)", unicode: false, maxLength: 200, nullable: false),
Address_Country = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
Address_City = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
Address_Street = table.Column<string>(type: "character varying(100)", unicode: false, maxLength: 100, nullable: false),
Address_Building = table.Column<string>(type: "character varying(10)", unicode: false, maxLength: 10, nullable: false),
PhoneNum = table.Column<string>(type: "character varying(13)", unicode: false, maxLength: 13, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PlaceOfWork", x => x.Id);
});
migrationBuilder.CreateTable(
name: "User",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Role = table.Column<int>(type: "integer", nullable: false),
Email = table.Column<string>(type: "character varying(254)", unicode: false, maxLength: 254, nullable: false),
Password = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_User", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Applicant",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
Name_FirstName = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
Name_Surname = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
Name_Patronymic = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: true),
Passport_Number = table.Column<string>(type: "character varying(20)", unicode: false, maxLength: 20, nullable: false),
Passport_Issuer = table.Column<string>(type: "character varying(200)", unicode: false, maxLength: 200, nullable: false),
Passport_IssueDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Passport_ExpirationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
BirthDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
CountryOfBirth = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
CityOfBirth = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
Citizenship = table.Column<string>(type: "character varying(30)", unicode: false, maxLength: 30, nullable: false),
CitizenshipByBirth = table.Column<string>(type: "character varying(30)", unicode: false, maxLength: 30, nullable: false),
Gender = table.Column<int>(type: "integer", nullable: false),
MaritalStatus = table.Column<int>(type: "integer", nullable: false),
FatherName_FirstName = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
FatherName_Surname = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
FatherName_Patronymic = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: true),
MotherName_FirstName = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
MotherName_Surname = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
MotherName_Patronymic = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: true),
JobTitle = table.Column<string>(type: "character varying(50)", unicode: false, maxLength: 50, nullable: false),
PlaceOfWorkId = table.Column<Guid>(type: "uuid", nullable: false),
IsNonResident = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Applicant", x => x.Id);
table.ForeignKey(
name: "FK_Applicant_PlaceOfWork_PlaceOfWorkId",
column: x => x.PlaceOfWorkId,
principalTable: "PlaceOfWork",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Applicant_User_UserId",
column: x => x.UserId,
principalTable: "User",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "VisaApplication",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ApplicantId = table.Column<Guid>(type: "uuid", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
ReentryPermit_Number = table.Column<string>(type: "character varying(25)", unicode: false, maxLength: 25, nullable: true),
ReentryPermit_ExpirationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
DestinationCountry = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
PermissionToDestCountry_ExpirationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
PermissionToDestCountry_Issuer = table.Column<string>(type: "character varying(200)", unicode: false, maxLength: 200, nullable: true),
VisaCategory = table.Column<int>(type: "integer", nullable: false),
ForGroup = table.Column<bool>(type: "boolean", nullable: false),
RequestedNumberOfEntries = table.Column<int>(type: "integer", nullable: false),
RequestDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
ValidDaysRequested = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_VisaApplication", x => x.Id);
table.ForeignKey(
name: "FK_VisaApplication_Applicant_ApplicantId",
column: x => x.ApplicantId,
principalTable: "Applicant",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PastVisa",
columns: table => new
{
VisaApplicationId = table.Column<Guid>(type: "uuid", nullable: false),
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
IssueDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Name = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false),
ExpirationDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PastVisa", x => new { x.VisaApplicationId, x.Id });
table.ForeignKey(
name: "FK_PastVisa_VisaApplication_VisaApplicationId",
column: x => x.VisaApplicationId,
principalTable: "VisaApplication",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PastVisit",
columns: table => new
{
VisaApplicationId = table.Column<Guid>(type: "uuid", nullable: false),
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
StartDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EndDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
DestinationCountry = table.Column<string>(type: "character varying(70)", unicode: false, maxLength: 70, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PastVisit", x => new { x.VisaApplicationId, x.Id });
table.ForeignKey(
name: "FK_PastVisit_VisaApplication_VisaApplicationId",
column: x => x.VisaApplicationId,
principalTable: "VisaApplication",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Applicant_PlaceOfWorkId",
table: "Applicant",
column: "PlaceOfWorkId");
migrationBuilder.CreateIndex(
name: "IX_Applicant_UserId",
table: "Applicant",
column: "UserId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_User_Email",
table: "User",
column: "Email",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_VisaApplication_ApplicantId",
table: "VisaApplication",
column: "ApplicantId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PastVisa");
migrationBuilder.DropTable(
name: "PastVisit");
migrationBuilder.DropTable(
name: "VisaApplication");
migrationBuilder.DropTable(
name: "Applicant");
migrationBuilder.DropTable(
name: "PlaceOfWork");
migrationBuilder.DropTable(
name: "User");
}
}
}

View File

@@ -0,0 +1,502 @@
// <auto-generated />
using System;
using Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Infrastructure.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20250509170104_TimeStampTypeChange")]
partial class TimeStampTypeChange
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Citizenship")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CitizenshipByBirth")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CityOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<string>("CountryOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<bool>("IsNonResident")
.HasColumnType("boolean");
b.Property<string>("JobTitle")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("MaritalStatus")
.HasColumnType("integer");
b.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PlaceOfWorkId");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("Applicant");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b.Property<string>("PhoneNum")
.IsRequired()
.HasMaxLength(13)
.IsUnicode(false)
.HasColumnType("character varying(13)");
b.HasKey("Id");
b.ToTable("PlaceOfWork");
});
modelBuilder.Entity("Domains.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(254)
.IsUnicode(false)
.HasColumnType("character varying(254)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("User");
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<bool>("ForGroup")
.HasColumnType("boolean");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp without time zone");
b.Property<int>("RequestedNumberOfEntries")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<int>("ValidDaysRequested")
.HasColumnType("integer");
b.Property<int>("VisaCategory")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ApplicantId");
b.ToTable("VisaApplication");
});
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.HasOne("Domains.ApplicantDomain.PlaceOfWork", "PlaceOfWork")
.WithMany()
.HasForeignKey("PlaceOfWorkId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Domains.Users.User", null)
.WithOne()
.HasForeignKey("Domains.ApplicantDomain.Applicant", "UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsOne("Domains.ApplicantDomain.Name", "FatherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "MotherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "Name", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Passport", "Passport", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(20)
.IsUnicode(false)
.HasColumnType("character varying(20)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.Navigation("FatherName")
.IsRequired();
b.Navigation("MotherName")
.IsRequired();
b.Navigation("Name")
.IsRequired();
b.Navigation("Passport")
.IsRequired();
b.Navigation("PlaceOfWork");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.OwnsOne("Domains.ApplicantDomain.Address", "Address", b1 =>
{
b1.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b1.Property<string>("Building")
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false)
.HasColumnType("character varying(10)");
b1.Property<string>("City")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Country")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Street")
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false)
.HasColumnType("character varying(100)");
b1.HasKey("PlaceOfWorkId");
b1.ToTable("PlaceOfWork");
b1.WithOwner()
.HasForeignKey("PlaceOfWorkId");
});
b.Navigation("Address")
.IsRequired();
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.HasOne("Domains.ApplicantDomain.Applicant", null)
.WithMany()
.HasForeignKey("ApplicantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsMany("Domains.VisaApplicationDomain.PastVisa", "PastVisas", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Name")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisa");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsMany("Domains.VisaApplicationDomain.PastVisit", "PastVisits", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<DateTime>("EndDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("StartDate")
.HasColumnType("timestamp without time zone");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisit");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.PermissionToDestCountry", "PermissionToDestCountry", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.ReentryPermit", "ReentryPermit", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(25)
.IsUnicode(false)
.HasColumnType("character varying(25)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.Navigation("PastVisas");
b.Navigation("PastVisits");
b.Navigation("PermissionToDestCountry");
b.Navigation("ReentryPermit");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,183 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Infrastructure.Migrations
{
/// <inheritdoc />
public partial class TimeStampTypeChange : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "RequestDate",
table: "VisaApplication",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "ReentryPermit_ExpirationDate",
table: "VisaApplication",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "PermissionToDestCountry_ExpirationDate",
table: "VisaApplication",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "StartDate",
table: "PastVisit",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "EndDate",
table: "PastVisit",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "IssueDate",
table: "PastVisa",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "ExpirationDate",
table: "PastVisa",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "Passport_IssueDate",
table: "Applicant",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "Passport_ExpirationDate",
table: "Applicant",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "BirthDate",
table: "Applicant",
type: "timestamp without time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "RequestDate",
table: "VisaApplication",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "ReentryPermit_ExpirationDate",
table: "VisaApplication",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "PermissionToDestCountry_ExpirationDate",
table: "VisaApplication",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "StartDate",
table: "PastVisit",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "EndDate",
table: "PastVisit",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "IssueDate",
table: "PastVisa",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "ExpirationDate",
table: "PastVisa",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "Passport_IssueDate",
table: "Applicant",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "Passport_ExpirationDate",
table: "Applicant",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
migrationBuilder.AlterColumn<DateTime>(
name: "BirthDate",
table: "Applicant",
type: "timestamp with time zone",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone");
}
}
}

View File

@@ -0,0 +1,499 @@
// <auto-generated />
using System;
using Infrastructure.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Infrastructure.Migrations
{
[DbContext(typeof(DatabaseContext))]
partial class DatabaseContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp without time zone");
b.Property<string>("Citizenship")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CitizenshipByBirth")
.IsRequired()
.HasMaxLength(30)
.IsUnicode(false)
.HasColumnType("character varying(30)");
b.Property<string>("CityOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<string>("CountryOfBirth")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<bool>("IsNonResident")
.HasColumnType("boolean");
b.Property<string>("JobTitle")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("MaritalStatus")
.HasColumnType("integer");
b.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PlaceOfWorkId");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("Applicant");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b.Property<string>("PhoneNum")
.IsRequired()
.HasMaxLength(13)
.IsUnicode(false)
.HasColumnType("character varying(13)");
b.HasKey("Id");
b.ToTable("PlaceOfWork");
});
modelBuilder.Entity("Domains.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(254)
.IsUnicode(false)
.HasColumnType("character varying(254)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.ToTable("User");
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b.Property<bool>("ForGroup")
.HasColumnType("boolean");
b.Property<DateTime>("RequestDate")
.HasColumnType("timestamp without time zone");
b.Property<int>("RequestedNumberOfEntries")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<int>("ValidDaysRequested")
.HasColumnType("integer");
b.Property<int>("VisaCategory")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ApplicantId");
b.ToTable("VisaApplication");
});
modelBuilder.Entity("Domains.ApplicantDomain.Applicant", b =>
{
b.HasOne("Domains.ApplicantDomain.PlaceOfWork", "PlaceOfWork")
.WithMany()
.HasForeignKey("PlaceOfWorkId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Domains.Users.User", null)
.WithOne()
.HasForeignKey("Domains.ApplicantDomain.Applicant", "UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsOne("Domains.ApplicantDomain.Name", "FatherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "MotherName", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Name", "Name", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Patronymic")
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.Property<string>("Surname")
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false)
.HasColumnType("character varying(50)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.OwnsOne("Domains.ApplicantDomain.Passport", "Passport", b1 =>
{
b1.Property<Guid>("ApplicantId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(20)
.IsUnicode(false)
.HasColumnType("character varying(20)");
b1.HasKey("ApplicantId");
b1.ToTable("Applicant");
b1.WithOwner()
.HasForeignKey("ApplicantId");
});
b.Navigation("FatherName")
.IsRequired();
b.Navigation("MotherName")
.IsRequired();
b.Navigation("Name")
.IsRequired();
b.Navigation("Passport")
.IsRequired();
b.Navigation("PlaceOfWork");
});
modelBuilder.Entity("Domains.ApplicantDomain.PlaceOfWork", b =>
{
b.OwnsOne("Domains.ApplicantDomain.Address", "Address", b1 =>
{
b1.Property<Guid>("PlaceOfWorkId")
.HasColumnType("uuid");
b1.Property<string>("Building")
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false)
.HasColumnType("character varying(10)");
b1.Property<string>("City")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Country")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<string>("Street")
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false)
.HasColumnType("character varying(100)");
b1.HasKey("PlaceOfWorkId");
b1.ToTable("PlaceOfWork");
b1.WithOwner()
.HasForeignKey("PlaceOfWorkId");
});
b.Navigation("Address")
.IsRequired();
});
modelBuilder.Entity("Domains.VisaApplicationDomain.VisaApplication", b =>
{
b.HasOne("Domains.ApplicantDomain.Applicant", null)
.WithMany()
.HasForeignKey("ApplicantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.OwnsMany("Domains.VisaApplicationDomain.PastVisa", "PastVisas", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("IssueDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Name")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisa");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsMany("Domains.VisaApplicationDomain.PastVisit", "PastVisits", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<string>("DestinationCountry")
.IsRequired()
.HasMaxLength(70)
.IsUnicode(false)
.HasColumnType("character varying(70)");
b1.Property<DateTime>("EndDate")
.HasColumnType("timestamp without time zone");
b1.Property<DateTime>("StartDate")
.HasColumnType("timestamp without time zone");
b1.HasKey("VisaApplicationId", "Id");
b1.ToTable("PastVisit");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.PermissionToDestCountry", "PermissionToDestCountry", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Issuer")
.IsRequired()
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnType("character varying(200)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.OwnsOne("Domains.VisaApplicationDomain.ReentryPermit", "ReentryPermit", b1 =>
{
b1.Property<Guid>("VisaApplicationId")
.HasColumnType("uuid");
b1.Property<DateTime>("ExpirationDate")
.HasColumnType("timestamp without time zone");
b1.Property<string>("Number")
.IsRequired()
.HasMaxLength(25)
.IsUnicode(false)
.HasColumnType("character varying(25)");
b1.HasKey("VisaApplicationId");
b1.ToTable("VisaApplication");
b1.WithOwner()
.HasForeignKey("VisaApplicationId");
});
b.Navigation("PastVisas");
b.Navigation("PastVisits");
b.Navigation("PermissionToDestCountry");
b.Navigation("ReentryPermit");
});
#pragma warning restore 612, 618
}
}
}