add employee management
This commit is contained in:
parent
f4611f029f
commit
5982fa7285
@ -0,0 +1,6 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||||
|
.Persistence.Repositories;
|
||||||
|
|
||||||
|
public interface EmployeeRepository : BaseRepository<Employee> { }
|
@ -28,6 +28,8 @@ public interface UnitOfWork : IDisposable
|
|||||||
|
|
||||||
CompanyRepository CompanyRepository { get; }
|
CompanyRepository CompanyRepository { get; }
|
||||||
|
|
||||||
|
EmployeeRepository EmployeeRepository { get; }
|
||||||
|
|
||||||
int Save();
|
int Save();
|
||||||
|
|
||||||
Task<int> SaveAsync(CancellationToken cancellationToken);
|
Task<int> SaveAsync(CancellationToken cancellationToken);
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Models;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.AddEmployee;
|
||||||
|
|
||||||
|
public record AddEmployeeCommand : IRequest<EmployeeDto>
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public Sex Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid CompanyGuid { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocumentModel> Documents { get; set; }
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using MediatR.Behaviors.Authorization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.AddEmployee;
|
||||||
|
|
||||||
|
public class AddEmployeeCommandAuthorizer :
|
||||||
|
AbstractRequestAuthorizer<AddEmployeeCommand>
|
||||||
|
{
|
||||||
|
private readonly SessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public AddEmployeeCommandAuthorizer(SessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildPolicy(AddEmployeeCommand request)
|
||||||
|
{
|
||||||
|
UseRequirement(new MustBeAuthenticatedRequirement
|
||||||
|
{
|
||||||
|
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||||
|
});
|
||||||
|
|
||||||
|
UseRequirement(new MustBeInRolesRequirement
|
||||||
|
{
|
||||||
|
RequiredRoles = [IdentityRole.Administrator],
|
||||||
|
UserRoles = _sessionUserService.Roles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
using AutoMapper;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.AddEmployee;
|
||||||
|
|
||||||
|
public class AddEmployeeCommandHandler :
|
||||||
|
IRequestHandler<AddEmployeeCommand, EmployeeDto>
|
||||||
|
{
|
||||||
|
private readonly UnitOfWork _unitOfWork;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
private readonly IStringLocalizer _localizer;
|
||||||
|
|
||||||
|
public AddEmployeeCommandHandler(
|
||||||
|
UnitOfWork unitOfWork,
|
||||||
|
IMapper mapper,
|
||||||
|
IStringLocalizer localizer)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_mapper = mapper;
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDto> Handle(
|
||||||
|
AddEmployeeCommand request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var parentEntity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||||
|
e => e.Guid == request.CompanyGuid, cancellationToken);
|
||||||
|
|
||||||
|
if (parentEntity == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException(
|
||||||
|
$"Parent entity with Guid: {request.CompanyGuid} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = await _unitOfWork.EmployeeRepository.GetOneAsync(
|
||||||
|
e =>
|
||||||
|
e.FirstName == request.FirstName &&
|
||||||
|
e.LastName == request.LastName &&
|
||||||
|
e.Patronymic == request.Patronymic &&
|
||||||
|
e.Sex == request.Sex &&
|
||||||
|
e.BirthDate == request.BirthDate &&
|
||||||
|
e.CompanyId == parentEntity.Id,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
throw new DuplicateEntityException();
|
||||||
|
}
|
||||||
|
|
||||||
|
entity = new Employee()
|
||||||
|
{
|
||||||
|
FirstName = request.FirstName,
|
||||||
|
LastName = request.LastName,
|
||||||
|
Patronymic = request.Patronymic,
|
||||||
|
Sex = request.Sex,
|
||||||
|
BirthDate = request.BirthDate,
|
||||||
|
Documents = request.Documents.Select(
|
||||||
|
d => new EmployeeDocument()
|
||||||
|
{
|
||||||
|
DocumentType = d.DocumentType,
|
||||||
|
Information = d.Information
|
||||||
|
})
|
||||||
|
.ToArray(),
|
||||||
|
Company = parentEntity
|
||||||
|
};
|
||||||
|
|
||||||
|
entity = await _unitOfWork.EmployeeRepository.AddOneAsync(
|
||||||
|
entity, cancellationToken);
|
||||||
|
|
||||||
|
await _unitOfWork.SaveAsync(cancellationToken);
|
||||||
|
_unitOfWork.Dispose();
|
||||||
|
|
||||||
|
return _mapper.Map<EmployeeDto>(entity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using FluentValidation;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.AddEmployee;
|
||||||
|
|
||||||
|
public class AddEmployeeCommandValidator : AbstractValidator<AddEmployeeCommand>
|
||||||
|
{
|
||||||
|
public AddEmployeeCommandValidator(
|
||||||
|
IStringLocalizer localizer,
|
||||||
|
SessionCultureService cultureService)
|
||||||
|
{
|
||||||
|
RuleFor(e => e.FirstName)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.LastName)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.Patronymic)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.Sex)
|
||||||
|
.Must((e, s) => Sex.Enumerations.ContainsValue(s))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
localizer["FluentValidation.MustBeInEnum"],
|
||||||
|
String.Join(
|
||||||
|
", ",
|
||||||
|
Sex.Enumerations.Values.Select(e => e.Name))));
|
||||||
|
|
||||||
|
RuleFor(e => e.BirthDate)
|
||||||
|
.GreaterThanOrEqualTo(DateOnly.FromDateTime(DateTime.UtcNow.AddYears(-100)))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||||
|
DateOnly.FromDateTime(DateTime.UtcNow.AddYears(-100))));
|
||||||
|
|
||||||
|
RuleForEach(e => e.Documents).ChildRules(d =>
|
||||||
|
{
|
||||||
|
d.RuleFor(d => d.DocumentType)
|
||||||
|
.Must(dt => DocumentType.Enumerations.ContainsValue(dt))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
localizer["FluentValidation.MustBeInEnum"],
|
||||||
|
String.Join(
|
||||||
|
", ",
|
||||||
|
DocumentType.Enumerations.Values.Select(e => e.Name))));
|
||||||
|
|
||||||
|
d.RuleFor(d => d.Information)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(256)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
256));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.DeleteEmployee;
|
||||||
|
|
||||||
|
public record DeleteEmployeeCommand : IRequest
|
||||||
|
{
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using MediatR.Behaviors.Authorization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.DeleteEmployee;
|
||||||
|
|
||||||
|
public class DeleteEmployeeCommandAuthorizer :
|
||||||
|
AbstractRequestAuthorizer<DeleteEmployeeCommand>
|
||||||
|
{
|
||||||
|
private readonly SessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public DeleteEmployeeCommandAuthorizer(SessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildPolicy(DeleteEmployeeCommand request)
|
||||||
|
{
|
||||||
|
UseRequirement(new MustBeAuthenticatedRequirement
|
||||||
|
{
|
||||||
|
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||||
|
});
|
||||||
|
|
||||||
|
UseRequirement(new MustBeInRolesRequirement
|
||||||
|
{
|
||||||
|
RequiredRoles = [IdentityRole.Administrator],
|
||||||
|
UserRoles = _sessionUserService.Roles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.DeleteEmployee;
|
||||||
|
|
||||||
|
public class DeleteEmployeeCommandHandler : IRequestHandler<DeleteEmployeeCommand>
|
||||||
|
{
|
||||||
|
private readonly UnitOfWork _unitOfWork;
|
||||||
|
|
||||||
|
public DeleteEmployeeCommandHandler(UnitOfWork unitOfWork)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(
|
||||||
|
DeleteEmployeeCommand request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var entity = await _unitOfWork.EmployeeRepository.GetOneAsync(
|
||||||
|
e => e.Guid == request.Guid, cancellationToken);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check for Vehicles that using this employee in Enrollments
|
||||||
|
// Delete if there are no such Vehicles
|
||||||
|
|
||||||
|
await _unitOfWork.EmployeeRepository.DeleteOneAsync(
|
||||||
|
entity, cancellationToken);
|
||||||
|
|
||||||
|
await _unitOfWork.SaveAsync(cancellationToken);
|
||||||
|
_unitOfWork.Dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.DeleteEmployee;
|
||||||
|
|
||||||
|
public class DeleteEmployeeCommandValidator : AbstractValidator<DeleteEmployeeCommand>
|
||||||
|
{
|
||||||
|
public DeleteEmployeeCommandValidator(IStringLocalizer localizer)
|
||||||
|
{
|
||||||
|
RuleFor(v => v.Guid)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Models;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.UpdateEmployee;
|
||||||
|
|
||||||
|
public record UpdateEmployeeCommand : IRequest<EmployeeDto>
|
||||||
|
{
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public Sex Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid CompanyGuid { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocumentModel> Documents { get; set; }
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using MediatR.Behaviors.Authorization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.UpdateEmployee;
|
||||||
|
|
||||||
|
public class UpdateEmployeeCommandAuthorizer :
|
||||||
|
AbstractRequestAuthorizer<UpdateEmployeeCommand>
|
||||||
|
{
|
||||||
|
private readonly SessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public UpdateEmployeeCommandAuthorizer(SessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildPolicy(UpdateEmployeeCommand request)
|
||||||
|
{
|
||||||
|
UseRequirement(new MustBeAuthenticatedRequirement
|
||||||
|
{
|
||||||
|
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||||
|
});
|
||||||
|
|
||||||
|
UseRequirement(new MustBeInRolesRequirement
|
||||||
|
{
|
||||||
|
RequiredRoles = [IdentityRole.Administrator],
|
||||||
|
UserRoles = _sessionUserService.Roles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||||
|
using AutoMapper;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.UpdateEmployee;
|
||||||
|
|
||||||
|
public class UpdateEmployeeCommandHandler :
|
||||||
|
IRequestHandler<UpdateEmployeeCommand, EmployeeDto>
|
||||||
|
{
|
||||||
|
private readonly UnitOfWork _unitOfWork;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
public IStringLocalizer _localizer { get; set; }
|
||||||
|
|
||||||
|
public UpdateEmployeeCommandHandler(
|
||||||
|
UnitOfWork unitOfWork,
|
||||||
|
IMapper mapper,
|
||||||
|
IStringLocalizer localizer)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_mapper = mapper;
|
||||||
|
_localizer = localizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDto> Handle(
|
||||||
|
UpdateEmployeeCommand request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var parentEntity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||||
|
e => e.Guid == request.CompanyGuid, cancellationToken);
|
||||||
|
|
||||||
|
if (parentEntity == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException(
|
||||||
|
$"Parent entity with Guid: {request.CompanyGuid} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var entity = await _unitOfWork.EmployeeRepository.GetOneAsync(
|
||||||
|
e =>
|
||||||
|
e.FirstName == request.FirstName &&
|
||||||
|
e.LastName == request.LastName &&
|
||||||
|
e.Patronymic == request.Patronymic &&
|
||||||
|
e.Sex == request.Sex &&
|
||||||
|
e.BirthDate == request.BirthDate &&
|
||||||
|
e.CompanyId == parentEntity.Id &&
|
||||||
|
e.Guid != request.Guid,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
throw new DuplicateEntityException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
entity = await _unitOfWork.EmployeeRepository.GetOneAsync(
|
||||||
|
e => e.Guid == request.Guid, e => e.Documents, cancellationToken);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
entity.Guid = request.Guid;
|
||||||
|
entity.FirstName = request.FirstName;
|
||||||
|
entity.LastName = request.LastName;
|
||||||
|
entity.Patronymic = request.Patronymic;
|
||||||
|
entity.Sex = request.Sex;
|
||||||
|
entity.BirthDate = request.BirthDate;
|
||||||
|
entity.CompanyId = parentEntity.Id;
|
||||||
|
|
||||||
|
entity.Company = parentEntity;
|
||||||
|
|
||||||
|
|
||||||
|
var requestEmployeeDocuments = request.Documents.Select(
|
||||||
|
d => new EmployeeDocument()
|
||||||
|
{
|
||||||
|
DocumentType = d.DocumentType,
|
||||||
|
Information = d.Information
|
||||||
|
});
|
||||||
|
|
||||||
|
var commonEmployeeDocuments = entity.Documents.IntersectBy(
|
||||||
|
requestEmployeeDocuments.Select(
|
||||||
|
ed => (ed.DocumentType, ed.Information)),
|
||||||
|
ed => (ed.DocumentType, ed.Information));
|
||||||
|
|
||||||
|
var newEmployeeDocuments = requestEmployeeDocuments.ExceptBy(
|
||||||
|
entity.Documents.Select(ed => (ed.DocumentType, ed.Information)),
|
||||||
|
ed => (ed.DocumentType, ed.Information));
|
||||||
|
|
||||||
|
var combinedEmployeeDocuments = commonEmployeeDocuments.UnionBy(
|
||||||
|
newEmployeeDocuments, ed => (ed.DocumentType, ed.Information));
|
||||||
|
|
||||||
|
entity.Documents = combinedEmployeeDocuments.ToList();
|
||||||
|
|
||||||
|
|
||||||
|
entity = await _unitOfWork.EmployeeRepository.UpdateOneAsync(
|
||||||
|
entity, cancellationToken);
|
||||||
|
|
||||||
|
await _unitOfWork.SaveAsync(cancellationToken);
|
||||||
|
_unitOfWork.Dispose();
|
||||||
|
|
||||||
|
return _mapper.Map<EmployeeDto>(entity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using FluentValidation;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Commands.UpdateEmployee;
|
||||||
|
|
||||||
|
public class UpdateEmployeeCommandValidator : AbstractValidator<UpdateEmployeeCommand>
|
||||||
|
{
|
||||||
|
public UpdateEmployeeCommandValidator(
|
||||||
|
IStringLocalizer localizer,
|
||||||
|
SessionCultureService cultureService)
|
||||||
|
{
|
||||||
|
RuleFor(v => v.Guid)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||||
|
|
||||||
|
RuleFor(e => e.FirstName)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.LastName)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.Patronymic)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(32)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
32));
|
||||||
|
|
||||||
|
RuleFor(e => e.Sex)
|
||||||
|
.Must((e, s) => Sex.Enumerations.ContainsValue(s))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
localizer["FluentValidation.MustBeInEnum"],
|
||||||
|
String.Join(
|
||||||
|
", ",
|
||||||
|
Sex.Enumerations.Values.Select(e => e.Name))));
|
||||||
|
|
||||||
|
RuleFor(e => e.BirthDate)
|
||||||
|
.GreaterThanOrEqualTo(DateOnly.FromDateTime(DateTime.UtcNow.AddYears(-100)))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||||
|
DateOnly.FromDateTime(DateTime.UtcNow.AddYears(-100))));
|
||||||
|
|
||||||
|
RuleForEach(e => e.Documents).ChildRules(d =>
|
||||||
|
{
|
||||||
|
d.RuleFor(d => d.DocumentType)
|
||||||
|
.Must(dt => DocumentType.Enumerations.ContainsValue(dt))
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
localizer["FluentValidation.MustBeInEnum"],
|
||||||
|
String.Join(
|
||||||
|
", ",
|
||||||
|
DocumentType.Enumerations.Values.Select(e => e.Name))));
|
||||||
|
|
||||||
|
d.RuleFor(d => d.Information)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||||
|
.MaximumLength(256)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
256));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
19
src/Application/Employees/EmployeeDocumentDto.cs
Normal file
19
src/Application/Employees/EmployeeDocumentDto.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Mappings;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees;
|
||||||
|
|
||||||
|
public sealed class EmployeeDocumentDto : IMapFrom<EmployeeDocument>
|
||||||
|
{
|
||||||
|
public string DocumentType { get; set; }
|
||||||
|
|
||||||
|
public string Information { get; set; }
|
||||||
|
|
||||||
|
public void Mapping(MappingProfile profile)
|
||||||
|
{
|
||||||
|
profile.CreateMap<EmployeeDocument, EmployeeDocumentDto>()
|
||||||
|
.ForMember(
|
||||||
|
d => d.DocumentType,
|
||||||
|
opt => opt.MapFrom(s => s.DocumentType.Name));
|
||||||
|
}
|
||||||
|
}
|
38
src/Application/Employees/EmployeeDto.cs
Normal file
38
src/Application/Employees/EmployeeDto.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Mappings;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees;
|
||||||
|
|
||||||
|
public sealed class EmployeeDto : IMapFrom<Employee>
|
||||||
|
{
|
||||||
|
public Guid Uuid { get; set; }
|
||||||
|
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public string Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid CompanyUuid { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocumentDto> Documents { get; set; }
|
||||||
|
|
||||||
|
public void Mapping(MappingProfile profile)
|
||||||
|
{
|
||||||
|
profile.CreateMap<Employee, EmployeeDto>()
|
||||||
|
.ForMember(
|
||||||
|
d => d.Uuid,
|
||||||
|
opt => opt.MapFrom(s => s.Guid))
|
||||||
|
.ForMember(
|
||||||
|
d => d.Sex,
|
||||||
|
opt => opt.MapFrom(s => s.Sex.Name))
|
||||||
|
.ForMember(
|
||||||
|
d => d.CompanyUuid,
|
||||||
|
opt => opt.MapFrom(s => s.Company.Guid));
|
||||||
|
}
|
||||||
|
}
|
10
src/Application/Employees/Models/EmployeeDocumentModel.cs
Normal file
10
src/Application/Employees/Models/EmployeeDocumentModel.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Models;
|
||||||
|
|
||||||
|
public sealed class EmployeeDocumentModel
|
||||||
|
{
|
||||||
|
public DocumentType DocumentType { get; set; }
|
||||||
|
|
||||||
|
public string Information { get; set; }
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployee;
|
||||||
|
|
||||||
|
public record GetEmployeeQuery : IRequest<EmployeeDto>
|
||||||
|
{
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using MediatR.Behaviors.Authorization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployee;
|
||||||
|
|
||||||
|
public class GetEmployeeQueryAuthorizer :
|
||||||
|
AbstractRequestAuthorizer<GetEmployeeQuery>
|
||||||
|
{
|
||||||
|
private readonly SessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public GetEmployeeQueryAuthorizer(SessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildPolicy(GetEmployeeQuery request)
|
||||||
|
{
|
||||||
|
UseRequirement(new MustBeAuthenticatedRequirement
|
||||||
|
{
|
||||||
|
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||||
|
});
|
||||||
|
|
||||||
|
UseRequirement(new MustBeInRolesRequirement
|
||||||
|
{
|
||||||
|
RequiredRoles = [IdentityRole.Administrator],
|
||||||
|
UserRoles = _sessionUserService.Roles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||||
|
using AutoMapper;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployee;
|
||||||
|
|
||||||
|
public class GetEmployeeQueryHandler :
|
||||||
|
IRequestHandler<GetEmployeeQuery, EmployeeDto>
|
||||||
|
{
|
||||||
|
private readonly UnitOfWork _unitOfWork;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
public GetEmployeeQueryHandler(
|
||||||
|
UnitOfWork unitOfWork,
|
||||||
|
IMapper mapper)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeDto> Handle(
|
||||||
|
GetEmployeeQuery request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var entity = await _unitOfWork.EmployeeRepository.GetOneAsync(
|
||||||
|
e => e.Guid == request.Guid, e => e.Documents,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Hydrate employees with companies
|
||||||
|
|
||||||
|
var company = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||||
|
e => e.Id == entity.CompanyId, cancellationToken);
|
||||||
|
|
||||||
|
entity.Company = company;
|
||||||
|
|
||||||
|
|
||||||
|
_unitOfWork.Dispose();
|
||||||
|
|
||||||
|
return _mapper.Map<EmployeeDto>(entity);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployee;
|
||||||
|
|
||||||
|
public class GetEmployeeQueryValidator : AbstractValidator<GetEmployeeQuery>
|
||||||
|
{
|
||||||
|
public GetEmployeeQueryValidator(IStringLocalizer localizer)
|
||||||
|
{
|
||||||
|
RuleFor(v => v.Guid)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployeesPage;
|
||||||
|
|
||||||
|
public record GetEmployeesPageQuery : IRequest<PaginatedList<EmployeeDto>>
|
||||||
|
{
|
||||||
|
public int PageNumber { get; set; } = 1;
|
||||||
|
|
||||||
|
public int PageSize { get; set; } = 10;
|
||||||
|
|
||||||
|
public string Search { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public string Sort { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public Sex? Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly? BirthDateGreaterThanOrEqualTo { get; set; }
|
||||||
|
|
||||||
|
public DateOnly? BirthDateLessThanOrEqualTo { get; set; }
|
||||||
|
|
||||||
|
public Guid? CompanyGuid { get; set; }
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using MediatR.Behaviors.Authorization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployeesPage;
|
||||||
|
|
||||||
|
public class GetEmployeesPageQueryAuthorizer :
|
||||||
|
AbstractRequestAuthorizer<GetEmployeesPageQuery>
|
||||||
|
{
|
||||||
|
private readonly SessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public GetEmployeesPageQueryAuthorizer(SessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildPolicy(GetEmployeesPageQuery request)
|
||||||
|
{
|
||||||
|
UseRequirement(new MustBeAuthenticatedRequirement
|
||||||
|
{
|
||||||
|
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||||
|
});
|
||||||
|
|
||||||
|
UseRequirement(new MustBeInRolesRequirement
|
||||||
|
{
|
||||||
|
RequiredRoles = [IdentityRole.Administrator],
|
||||||
|
UserRoles = _sessionUserService.Roles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
using MediatR;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||||
|
using AutoMapper;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployeesPage;
|
||||||
|
|
||||||
|
public class GetEmployeesPageQueryHandler :
|
||||||
|
IRequestHandler<GetEmployeesPageQuery, PaginatedList<EmployeeDto>>
|
||||||
|
{
|
||||||
|
private readonly UnitOfWork _unitOfWork;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
public GetEmployeesPageQueryHandler(
|
||||||
|
UnitOfWork unitOfWork,
|
||||||
|
IMapper mapper)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PaginatedList<EmployeeDto>> Handle(
|
||||||
|
GetEmployeesPageQuery request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var paginatedList = await _unitOfWork.EmployeeRepository.GetPageAsync(
|
||||||
|
e =>
|
||||||
|
(e.FirstName.ToLower().Contains(request.Search.ToLower()) ||
|
||||||
|
e.LastName.ToLower().Contains(request.Search.ToLower()) ||
|
||||||
|
e.Patronymic.ToLower().Contains(request.Search.ToLower()) ||
|
||||||
|
e.Documents
|
||||||
|
.Select(d => d.Information.ToLower())
|
||||||
|
.Contains(request.Search.ToLower())) &&
|
||||||
|
(request.CompanyGuid != null
|
||||||
|
? e.Company.Guid == request.CompanyGuid
|
||||||
|
: true) &&
|
||||||
|
(request.Sex != null
|
||||||
|
? e.Sex == request.Sex
|
||||||
|
: true) &&
|
||||||
|
(request.BirthDateLessThanOrEqualTo != null
|
||||||
|
? e.BirthDate <= request.BirthDateLessThanOrEqualTo
|
||||||
|
: true) &&
|
||||||
|
(request.BirthDateGreaterThanOrEqualTo != null
|
||||||
|
? e.BirthDate >= request.BirthDateGreaterThanOrEqualTo
|
||||||
|
: true),
|
||||||
|
e => e.Documents,
|
||||||
|
request.PageNumber, request.PageSize,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
|
||||||
|
// Hydrate employees with companies
|
||||||
|
|
||||||
|
var companies = await _unitOfWork.CompanyRepository.GetPageAsync(
|
||||||
|
e => paginatedList.Items.Select(e => e.CompanyId).Contains(e.Id),
|
||||||
|
1, paginatedList.Items.Count, cancellationToken);
|
||||||
|
|
||||||
|
foreach (var employee in paginatedList.Items)
|
||||||
|
{
|
||||||
|
employee.Company =
|
||||||
|
companies.Items.First(c => c.Id == employee.CompanyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var mappedItems = _mapper
|
||||||
|
.ProjectTo<EmployeeDto>(paginatedList.Items.AsQueryable());
|
||||||
|
|
||||||
|
mappedItems = QueryableExtension<EmployeeDto>
|
||||||
|
.ApplySort(mappedItems, request.Sort);
|
||||||
|
|
||||||
|
_unitOfWork.Dispose();
|
||||||
|
|
||||||
|
return new PaginatedList<EmployeeDto>(
|
||||||
|
mappedItems.ToList(),
|
||||||
|
paginatedList.TotalCount, request.PageNumber,
|
||||||
|
request.PageSize);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||||
|
using FluentValidation;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployeesPage;
|
||||||
|
|
||||||
|
public class GetEmployeesPageQueryValidator : AbstractValidator<GetEmployeesPageQuery>
|
||||||
|
{
|
||||||
|
public GetEmployeesPageQueryValidator(
|
||||||
|
IStringLocalizer localizer,
|
||||||
|
SessionCultureService cultureService)
|
||||||
|
{
|
||||||
|
RuleFor(v => v.PageNumber)
|
||||||
|
.GreaterThanOrEqualTo(1)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||||
|
1));
|
||||||
|
|
||||||
|
RuleFor(v => v.PageSize)
|
||||||
|
.GreaterThanOrEqualTo(1)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||||
|
1))
|
||||||
|
.LessThanOrEqualTo(50)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.LessThanOrEqualTo"],
|
||||||
|
50));
|
||||||
|
|
||||||
|
RuleFor(v => v.Search)
|
||||||
|
.MaximumLength(64)
|
||||||
|
.WithMessage(
|
||||||
|
String.Format(
|
||||||
|
cultureService.Culture,
|
||||||
|
localizer["FluentValidation.MaximumLength"],
|
||||||
|
64));
|
||||||
|
}
|
||||||
|
}
|
19
src/Application/Employees/ViewModels/AddEmployeeViewModel.cs
Normal file
19
src/Application/Employees/ViewModels/AddEmployeeViewModel.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.ViewModels;
|
||||||
|
|
||||||
|
public sealed class AddEmployeeViewModel
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public string Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid CompanyUuid { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocumentViewModel> Documents { get; set; }
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.ViewModels;
|
||||||
|
|
||||||
|
public sealed class EmployeeDocumentViewModel
|
||||||
|
{
|
||||||
|
public string DocumentType { get; set; }
|
||||||
|
|
||||||
|
public string Information { get; set; }
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.ViewModels;
|
||||||
|
|
||||||
|
public sealed class GetEmployeesPageFilterViewModel
|
||||||
|
{
|
||||||
|
public string? Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly? BirthDateGreaterThanOrEqualTo { get; set; }
|
||||||
|
|
||||||
|
public DateOnly? BirthDateLessThanOrEqualTo { get; set; }
|
||||||
|
|
||||||
|
public Guid? CompanyUuid { get; set; }
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Application.Employees.ViewModels;
|
||||||
|
|
||||||
|
public sealed class UpdateEmployeeViewModel
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public string Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid CompanyUuid { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocumentViewModel> Documents { get; set; }
|
||||||
|
}
|
@ -2,8 +2,8 @@
|
|||||||
"FluentValidation": {
|
"FluentValidation": {
|
||||||
"MaximumLength": "Must less than {0:G} characters.",
|
"MaximumLength": "Must less than {0:G} characters.",
|
||||||
"NotEmpty": "Must not be empty.",
|
"NotEmpty": "Must not be empty.",
|
||||||
"GreaterThanOrEqualTo": "Must be greater than or equal to {0:G}.",
|
"GreaterThanOrEqualTo": "Must be greater than or equal to {0}.",
|
||||||
"LessThanOrEqualTo": "Must be less than or equal to {0:G}.",
|
"LessThanOrEqualTo": "Must be less than or equal to {0}.",
|
||||||
"MustBeInEnum": "Must be one of the following: {0}.",
|
"MustBeInEnum": "Must be one of the following: {0}.",
|
||||||
"IsEmail": "Must be a valid email address according to RFC 5321.",
|
"IsEmail": "Must be a valid email address according to RFC 5321.",
|
||||||
"IsPhoneNumber": "Must be a valid phone number according to ITU-T E.164 with no separator characters."
|
"IsPhoneNumber": "Must be a valid phone number according to ITU-T E.164 with no separator characters."
|
||||||
|
@ -11,5 +11,7 @@ public sealed class Company : EntityBase
|
|||||||
public string ContactPhoneNumber { get; set; }
|
public string ContactPhoneNumber { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public ICollection<Employee> Employees { get; set; }
|
||||||
|
|
||||||
public ICollection<Vehicle> Vehicles { get; set; }
|
public ICollection<Vehicle> Vehicles { get; set; }
|
||||||
}
|
}
|
||||||
|
23
src/Domain/Entities/Employee.cs
Normal file
23
src/Domain/Entities/Employee.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
public sealed class Employee : EntityBase
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
|
||||||
|
public Sex Sex { get; set; }
|
||||||
|
|
||||||
|
public DateOnly BirthDate { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public long CompanyId { get; set; }
|
||||||
|
|
||||||
|
public Company Company { get; set; }
|
||||||
|
|
||||||
|
public ICollection<EmployeeDocument> Documents { get; set; }
|
||||||
|
}
|
15
src/Domain/Entities/EmployeeDocument.cs
Normal file
15
src/Domain/Entities/EmployeeDocument.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
public sealed class EmployeeDocument : EntityBase
|
||||||
|
{
|
||||||
|
public DocumentType DocumentType { get; set; }
|
||||||
|
|
||||||
|
public string Information { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public long EmployeeId { get; set; }
|
||||||
|
|
||||||
|
public Employee Employee { get; set; }
|
||||||
|
}
|
@ -20,4 +20,7 @@ public class VehicleEnrollment : EntityBase
|
|||||||
|
|
||||||
|
|
||||||
public ICollection<RouteAddressDetail> RouteAddressDetails { get; set; }
|
public ICollection<RouteAddressDetail> RouteAddressDetails { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public ICollection<Ticket> Tickets { get; set; }
|
||||||
}
|
}
|
||||||
|
16
src/Domain/Enums/DocumentType.cs
Normal file
16
src/Domain/Enums/DocumentType.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
|
||||||
|
// Do not forget to update the schema of your database when changing
|
||||||
|
// this class (if you use it with a database)
|
||||||
|
|
||||||
|
public abstract class DocumentType : Enumeration<DocumentType>
|
||||||
|
{
|
||||||
|
public static readonly DocumentType Passport = new PassportDocumentType();
|
||||||
|
|
||||||
|
protected DocumentType(int value, string name) : base(value, name) { }
|
||||||
|
|
||||||
|
private sealed class PassportDocumentType : DocumentType
|
||||||
|
{
|
||||||
|
public PassportDocumentType() : base(0, "passport") { }
|
||||||
|
}
|
||||||
|
}
|
22
src/Domain/Enums/Sex.cs
Normal file
22
src/Domain/Enums/Sex.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
|
||||||
|
// Do not forget to update the schema of your database when changing
|
||||||
|
// this class (if you use it with a database)
|
||||||
|
|
||||||
|
public abstract class Sex : Enumeration<Sex>
|
||||||
|
{
|
||||||
|
public static readonly Sex Male = new MaleSex();
|
||||||
|
public static readonly Sex Female = new FemaleSex();
|
||||||
|
|
||||||
|
protected Sex(int value, string name) : base(value, name) { }
|
||||||
|
|
||||||
|
private sealed class MaleSex : Sex
|
||||||
|
{
|
||||||
|
public MaleSex() : base(Int32.MaxValue, "male") { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class FemaleSex : Sex
|
||||||
|
{
|
||||||
|
public FemaleSex() : base(Int32.MinValue, "female") { }
|
||||||
|
}
|
||||||
|
}
|
212
src/HttpApi/Controllers/EmployeesController.cs
Normal file
212
src/HttpApi/Controllers/EmployeesController.cs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||||
|
using cuqmbr.TravelGuide.Application.Common.ViewModels;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Commands.AddEmployee;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployeesPage;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Queries.GetEmployee;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Commands.UpdateEmployee;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Commands.DeleteEmployee;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.ViewModels;
|
||||||
|
using cuqmbr.TravelGuide.Application.Employees.Models;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.HttpApi.Controllers;
|
||||||
|
|
||||||
|
[Route("employees")]
|
||||||
|
public class EmployeesController : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpPost]
|
||||||
|
[SwaggerOperation("Add an employee")]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status201Created, "Object successfuly created",
|
||||||
|
typeof(EmployeeDto))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||||
|
typeof(HttpValidationProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status403Forbidden,
|
||||||
|
"Not enough privileges to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status404NotFound, "One or more addresses was not found",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
public async Task<ActionResult<EmployeeDto>> Add(
|
||||||
|
[FromBody] AddEmployeeViewModel viewModel,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return StatusCode(
|
||||||
|
StatusCodes.Status201Created,
|
||||||
|
await Mediator.Send(
|
||||||
|
new AddEmployeeCommand()
|
||||||
|
{
|
||||||
|
FirstName = viewModel.FirstName,
|
||||||
|
LastName = viewModel.LastName,
|
||||||
|
Patronymic = viewModel.Patronymic,
|
||||||
|
Sex = Sex.FromName(viewModel.Sex),
|
||||||
|
BirthDate = viewModel.BirthDate,
|
||||||
|
Documents = viewModel.Documents.Select(
|
||||||
|
e => new EmployeeDocumentModel()
|
||||||
|
{
|
||||||
|
DocumentType = DocumentType.FromName(e.DocumentType),
|
||||||
|
Information = e.Information
|
||||||
|
|
||||||
|
}).ToArray(),
|
||||||
|
CompanyGuid = viewModel.CompanyUuid
|
||||||
|
},
|
||||||
|
cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[SwaggerOperation("Get a list of all employees")]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status200OK, "Request successful",
|
||||||
|
typeof(PaginatedList<EmployeeDto>))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||||
|
typeof(HttpValidationProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status403Forbidden,
|
||||||
|
"Not enough privileges to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
public async Task<PaginatedList<EmployeeDto>> GetPage(
|
||||||
|
[FromQuery] PageQuery pageQuery, [FromQuery] SearchQuery searchQuery,
|
||||||
|
[FromQuery] SortQuery sortQuery,
|
||||||
|
[FromQuery] GetEmployeesPageFilterViewModel filterQuery,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await Mediator.Send(
|
||||||
|
new GetEmployeesPageQuery()
|
||||||
|
{
|
||||||
|
PageNumber = pageQuery.PageNumber,
|
||||||
|
PageSize = pageQuery.PageSize,
|
||||||
|
Search = searchQuery.Search,
|
||||||
|
Sort = sortQuery.Sort,
|
||||||
|
Sex = Sex.FromName(filterQuery.Sex),
|
||||||
|
BirthDateLessThanOrEqualTo =
|
||||||
|
filterQuery.BirthDateLessThanOrEqualTo,
|
||||||
|
BirthDateGreaterThanOrEqualTo =
|
||||||
|
filterQuery.BirthDateGreaterThanOrEqualTo,
|
||||||
|
CompanyGuid = filterQuery.CompanyUuid
|
||||||
|
},
|
||||||
|
cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{uuid:guid}")]
|
||||||
|
[SwaggerOperation("Get an employee by uuid")]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status200OK, "Request successful", typeof(EmployeeDto))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||||
|
typeof(HttpValidationProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status403Forbidden,
|
||||||
|
"Not enough privileges to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status404NotFound, "Object not found", typeof(EmployeeDto))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
public async Task<EmployeeDto> Get(
|
||||||
|
[FromRoute] Guid uuid,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await Mediator.Send(new GetEmployeeQuery() { Guid = uuid },
|
||||||
|
cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{uuid:guid}")]
|
||||||
|
[SwaggerOperation("Update an employee")]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Object already exists",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||||
|
typeof(HttpValidationProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status403Forbidden,
|
||||||
|
"Not enough privileges to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status404NotFound, "Object not found", typeof(EmployeeDto))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status404NotFound, "One or more addresses was not found",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
public async Task<EmployeeDto> Update(
|
||||||
|
[FromRoute] Guid uuid,
|
||||||
|
[FromBody] UpdateEmployeeViewModel viewModel,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await Mediator.Send(
|
||||||
|
new UpdateEmployeeCommand()
|
||||||
|
{
|
||||||
|
Guid = uuid,
|
||||||
|
FirstName = viewModel.FirstName,
|
||||||
|
LastName = viewModel.LastName,
|
||||||
|
Patronymic = viewModel.Patronymic,
|
||||||
|
Sex = Sex.FromName(viewModel.Sex),
|
||||||
|
BirthDate = viewModel.BirthDate,
|
||||||
|
Documents = viewModel.Documents.Select(
|
||||||
|
e => new EmployeeDocumentModel()
|
||||||
|
{
|
||||||
|
DocumentType = DocumentType.FromName(e.DocumentType),
|
||||||
|
Information = e.Information
|
||||||
|
|
||||||
|
}).ToArray(),
|
||||||
|
CompanyGuid = viewModel.CompanyUuid
|
||||||
|
},
|
||||||
|
cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{uuid:guid}")]
|
||||||
|
[SwaggerOperation("Delete an employee")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status204NoContent, "Request successful")]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||||
|
typeof(HttpValidationProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status403Forbidden,
|
||||||
|
"Not enough privileges to perform an action",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status404NotFound, "Object not found",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
[SwaggerResponse(
|
||||||
|
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||||
|
typeof(ProblemDetails))]
|
||||||
|
public async Task<IActionResult> Delete(
|
||||||
|
[FromRoute] Guid uuid,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await Mediator.Send(
|
||||||
|
new DeleteEmployeeCommand() { Guid = uuid },
|
||||||
|
cancellationToken);
|
||||||
|
return StatusCode(StatusCodes.Status204NoContent);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using cuqmbr.TravelGuide.Domain.Enums;
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
using cuqmbr.TravelGuide.Domain.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using cuqmbr.TravelGuide.Persistence.TypeConverters;
|
using cuqmbr.TravelGuide.Persistence.TypeConverters;
|
||||||
|
|
||||||
@ -10,11 +9,6 @@ public class InMemoryDbContext : DbContext
|
|||||||
public InMemoryDbContext(DbContextOptions<InMemoryDbContext> options)
|
public InMemoryDbContext(DbContextOptions<InMemoryDbContext> options)
|
||||||
: base(options) { }
|
: base(options) { }
|
||||||
|
|
||||||
public DbSet<Country> Countries { get => Set<Country>(); }
|
|
||||||
public DbSet<Region> Regions { get => Set<Region>(); }
|
|
||||||
public DbSet<City> Cities { get => Set<City>(); }
|
|
||||||
public DbSet<Address> Addresses { get => Set<Address>(); }
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(builder);
|
base.OnModelCreating(builder);
|
||||||
|
@ -27,6 +27,7 @@ public sealed class InMemoryUnitOfWork : UnitOfWork
|
|||||||
RouteAddressRepository =
|
RouteAddressRepository =
|
||||||
new InMemoryRouteAddressRepository(_dbContext);
|
new InMemoryRouteAddressRepository(_dbContext);
|
||||||
CompanyRepository = new InMemoryCompanyRepository(_dbContext);
|
CompanyRepository = new InMemoryCompanyRepository(_dbContext);
|
||||||
|
EmployeeRepository = new InMemoryEmployeeRepository(_dbContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CountryRepository CountryRepository { get; init; }
|
public CountryRepository CountryRepository { get; init; }
|
||||||
@ -53,6 +54,8 @@ public sealed class InMemoryUnitOfWork : UnitOfWork
|
|||||||
|
|
||||||
public CompanyRepository CompanyRepository { get; init; }
|
public CompanyRepository CompanyRepository { get; init; }
|
||||||
|
|
||||||
|
public EmployeeRepository EmployeeRepository { get; init; }
|
||||||
|
|
||||||
public int Save()
|
public int Save()
|
||||||
{
|
{
|
||||||
return _dbContext.SaveChanges();
|
return _dbContext.SaveChanges();
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence.Repositories;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.InMemory.Repositories;
|
||||||
|
|
||||||
|
public sealed class InMemoryEmployeeRepository :
|
||||||
|
InMemoryBaseRepository<Employee>, EmployeeRepository
|
||||||
|
{
|
||||||
|
public InMemoryEmployeeRepository(InMemoryDbContext dbContext)
|
||||||
|
: base(dbContext) { }
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.PostgreSql.Configurations;
|
||||||
|
|
||||||
|
public class EmployeeConfiguration : BaseConfiguration<Employee>
|
||||||
|
{
|
||||||
|
public override void Configure(EntityTypeBuilder<Employee> builder)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.Property(e => e.Sex)
|
||||||
|
.HasColumnName("sex")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.ToTable(
|
||||||
|
"employees",
|
||||||
|
e => e.HasCheckConstraint(
|
||||||
|
"ck_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(e => e.Sex)
|
||||||
|
.Metadata.GetColumnName()}",
|
||||||
|
$"{builder.Property(e => e.Sex)
|
||||||
|
.Metadata.GetColumnName()} IN ('{String
|
||||||
|
.Join("', '", Sex.Enumerations
|
||||||
|
.Values.Select(v => v.Name))}')"));
|
||||||
|
|
||||||
|
base.Configure(builder);
|
||||||
|
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(e => e.FirstName)
|
||||||
|
.HasColumnName("first_name")
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(e => e.LastName)
|
||||||
|
.HasColumnName("last_name")
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(e => e.Patronymic)
|
||||||
|
.HasColumnName("patronymic")
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(e => e.BirthDate)
|
||||||
|
.HasColumnName("birth_date")
|
||||||
|
.HasColumnType("date")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(e => e.CompanyId)
|
||||||
|
.HasColumnName("company_id")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasOne(e => e.Company)
|
||||||
|
.WithMany(c => c.Employees)
|
||||||
|
.HasForeignKey(e => e.CompanyId)
|
||||||
|
.HasConstraintName(
|
||||||
|
"fk_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(e => e.CompanyId).Metadata.GetColumnName()}")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasIndex(e => e.CompanyId)
|
||||||
|
.HasDatabaseName(
|
||||||
|
"ix_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(e => e.CompanyId).Metadata.GetColumnName()}");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.PostgreSql.Configurations;
|
||||||
|
|
||||||
|
public class EmployeeDocumentConfiguration : BaseConfiguration<EmployeeDocument>
|
||||||
|
{
|
||||||
|
public override void Configure(EntityTypeBuilder<EmployeeDocument> builder)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.Property(ed => ed.DocumentType)
|
||||||
|
.HasColumnName("document_type")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.ToTable(
|
||||||
|
"employee_documents",
|
||||||
|
ed => ed.HasCheckConstraint(
|
||||||
|
"ck_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(ed => ed.DocumentType)
|
||||||
|
.Metadata.GetColumnName()}",
|
||||||
|
$"{builder.Property(ed => ed.DocumentType)
|
||||||
|
.Metadata.GetColumnName()} IN ('{String
|
||||||
|
.Join("', '", DocumentType.Enumerations
|
||||||
|
.Values.Select(v => v.Name))}')"));
|
||||||
|
|
||||||
|
base.Configure(builder);
|
||||||
|
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(ed => ed.Information)
|
||||||
|
.HasColumnName("information")
|
||||||
|
.HasColumnType("varchar(256)")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Property(ed => ed.EmployeeId)
|
||||||
|
.HasColumnName("employee_id")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.IsRequired(true);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasOne(ed => ed.Employee)
|
||||||
|
.WithMany(ed => ed.Documents)
|
||||||
|
.HasForeignKey(ed => ed.EmployeeId)
|
||||||
|
.HasConstraintName(
|
||||||
|
"fk_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(ed => ed.EmployeeId).Metadata.GetColumnName()}")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasIndex(ed => ed.EmployeeId)
|
||||||
|
.HasDatabaseName(
|
||||||
|
"ix_" +
|
||||||
|
$"{builder.Metadata.GetTableName()}_" +
|
||||||
|
$"{builder.Property(ed => ed.EmployeeId).Metadata.GetColumnName()}");
|
||||||
|
}
|
||||||
|
}
|
841
src/Persistence/PostgreSql/Migrations/20250515164353_Add_Employee_and_EmployeeDocument.Designer.cs
generated
Normal file
841
src/Persistence/PostgreSql/Migrations/20250515164353_Add_Employee_and_EmployeeDocument.Designer.cs
generated
Normal file
@ -0,0 +1,841 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using cuqmbr.TravelGuide.Persistence.PostgreSql;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Persistence.PostgreSql.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(PostgreSqlDbContext))]
|
||||||
|
[Migration("20250515164353_Add_Employee_and_EmployeeDocument")]
|
||||||
|
partial class Add_Employee_and_EmployeeDocument
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasDefaultSchema("application")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("addresses_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("cities_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("companies_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("countries_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("employee_documents_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("employees_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("regions_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("route_address_details_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("route_addresses_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("routes_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("vehicle_enrollments_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("vehicles_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.addresses_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "addresses_id_sequence");
|
||||||
|
|
||||||
|
b.Property<long>("CityId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("city_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<double>("Latitude")
|
||||||
|
.HasColumnType("double precision");
|
||||||
|
|
||||||
|
b.Property<double>("Longitude")
|
||||||
|
.HasColumnType("double precision");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(128)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("VehicleType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(16)")
|
||||||
|
.HasColumnName("vehicle_type");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_addresses");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_addresses_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("CityId")
|
||||||
|
.HasDatabaseName("ix_addresses_city_id");
|
||||||
|
|
||||||
|
b.ToTable("addresses", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_addresses_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.City", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.cities_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "cities_id_sequence");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<long>("RegionId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("region_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_cities");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_cities_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("RegionId")
|
||||||
|
.HasDatabaseName("ix_cities_region_id");
|
||||||
|
|
||||||
|
b.ToTable("cities", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Company", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.companies_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "companies_id_sequence");
|
||||||
|
|
||||||
|
b.Property<string>("ContactEmail")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(256)")
|
||||||
|
.HasColumnName("contact_email");
|
||||||
|
|
||||||
|
b.Property<string>("ContactPhoneNumber")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("contact_phone_number");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("LegalAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(256)")
|
||||||
|
.HasColumnName("legal_address");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_companies");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_companies_uuid");
|
||||||
|
|
||||||
|
b.ToTable("companies", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Country", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.countries_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "countries_id_sequence");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_countries");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_countries_uuid");
|
||||||
|
|
||||||
|
b.ToTable("countries", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.employees_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "employees_id_sequence");
|
||||||
|
|
||||||
|
b.Property<DateOnly>("BirthDate")
|
||||||
|
.HasColumnType("date")
|
||||||
|
.HasColumnName("birth_date");
|
||||||
|
|
||||||
|
b.Property<long>("CompanyId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("company_id");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("first_name");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("last_name");
|
||||||
|
|
||||||
|
b.Property<string>("Patronymic")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("patronymic");
|
||||||
|
|
||||||
|
b.Property<string>("Sex")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("sex");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_employees");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_employees_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("CompanyId")
|
||||||
|
.HasDatabaseName("ix_employees_company_id");
|
||||||
|
|
||||||
|
b.ToTable("employees", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_employees_sex", "sex IN ('male', 'female')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.EmployeeDocument", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.employee_documents_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "employee_documents_id_sequence");
|
||||||
|
|
||||||
|
b.Property<string>("DocumentType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("document_type");
|
||||||
|
|
||||||
|
b.Property<long>("EmployeeId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("employee_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Information")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(256)")
|
||||||
|
.HasColumnName("information");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_employee_documents");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_employee_documents_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("EmployeeId")
|
||||||
|
.HasDatabaseName("ix_employee_documents_employee_id");
|
||||||
|
|
||||||
|
b.ToTable("employee_documents", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_employee_documents_document_type", "document_type IN ('passport')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.regions_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "regions_id_sequence");
|
||||||
|
|
||||||
|
b.Property<long>("CountryId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("country_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_regions");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_regions_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("CountryId")
|
||||||
|
.HasDatabaseName("ix_regions_country_id");
|
||||||
|
|
||||||
|
b.ToTable("regions", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Route", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.routes_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "routes_id_sequence");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("VehicleType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(16)")
|
||||||
|
.HasColumnName("vehicle_type");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_routes");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_routes_uuid");
|
||||||
|
|
||||||
|
b.ToTable("routes", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_routes_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.RouteAddress", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.route_addresses_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "route_addresses_id_sequence");
|
||||||
|
|
||||||
|
b.Property<long>("AddressId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("address_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<short>("Order")
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("order");
|
||||||
|
|
||||||
|
b.Property<long>("RouteId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("route_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_route_addresses");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_route_addresses_uuid");
|
||||||
|
|
||||||
|
b.HasAlternateKey("AddressId", "RouteId", "Order")
|
||||||
|
.HasName("altk_route_addresses_address_id_route_id_order");
|
||||||
|
|
||||||
|
b.HasIndex("AddressId")
|
||||||
|
.HasDatabaseName("ix_route_addresses_address_id");
|
||||||
|
|
||||||
|
b.HasIndex("RouteId")
|
||||||
|
.HasDatabaseName("ix_route_addresses_route_id");
|
||||||
|
|
||||||
|
b.ToTable("route_addresses", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.RouteAddressDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.route_address_details_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "route_address_details_id_sequence");
|
||||||
|
|
||||||
|
b.Property<decimal>("CostToNextAddress")
|
||||||
|
.HasColumnType("numeric(24,12)")
|
||||||
|
.HasColumnName("cost_to_next_address");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("CurrentAddressStopTime")
|
||||||
|
.HasColumnType("interval")
|
||||||
|
.HasColumnName("current_address_stop_time");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<long>("RouteAddressId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("route_address_id");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("TimeToNextAddress")
|
||||||
|
.HasColumnType("interval")
|
||||||
|
.HasColumnName("time_to_next_address");
|
||||||
|
|
||||||
|
b.Property<long>("VehicleEnrollmentId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("vehicle_enrollment_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_route_address_details");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_route_address_details_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("RouteAddressId")
|
||||||
|
.HasDatabaseName("ix_route_address_details_route_address_id");
|
||||||
|
|
||||||
|
b.HasIndex("VehicleEnrollmentId")
|
||||||
|
.HasDatabaseName("ix_route_address_details_vehicle_enrollment_id");
|
||||||
|
|
||||||
|
b.ToTable("route_address_details", "application");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Vehicle", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.vehicles_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "vehicles_id_sequence");
|
||||||
|
|
||||||
|
b.Property<long>("CompanyId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("company_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("VehicleType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(16)")
|
||||||
|
.HasColumnName("vehicle_type");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_vehicles");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_vehicles_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("CompanyId")
|
||||||
|
.HasDatabaseName("ix_vehicles_company_id");
|
||||||
|
|
||||||
|
b.ToTable("vehicles", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_vehicles_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.HasDiscriminator<string>("VehicleType");
|
||||||
|
|
||||||
|
b.UseTphMappingStrategy();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.VehicleEnrollment", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.vehicle_enrollments_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "vehicle_enrollments_id_sequence");
|
||||||
|
|
||||||
|
b.Property<string>("Currency")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(8)")
|
||||||
|
.HasColumnName("currency");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("DepartureTime")
|
||||||
|
.HasColumnType("timestamptz")
|
||||||
|
.HasColumnName("departure_time");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<long>("RouteId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("route_id");
|
||||||
|
|
||||||
|
b.Property<long>("VehicleId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("vehicle_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_vehicle_enrollments");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_vehicle_enrollments_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("RouteId")
|
||||||
|
.HasDatabaseName("ix_vehicle_enrollments_route_id");
|
||||||
|
|
||||||
|
b.HasIndex("VehicleId")
|
||||||
|
.HasDatabaseName("ix_vehicle_enrollments_vehicle_id");
|
||||||
|
|
||||||
|
b.ToTable("vehicle_enrollments", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_vehicle_enrollments_currency", "currency IN ('DEFAULT', 'USD', 'EUR', 'UAH')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Aircraft", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("cuqmbr.TravelGuide.Domain.Entities.Vehicle");
|
||||||
|
|
||||||
|
b.Property<short>("Capacity")
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("capacity");
|
||||||
|
|
||||||
|
b.Property<string>("Model")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("model");
|
||||||
|
|
||||||
|
b.Property<string>("Number")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("number");
|
||||||
|
|
||||||
|
b.ToTable(t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_vehicles_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue("aircraft");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Bus", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("cuqmbr.TravelGuide.Domain.Entities.Vehicle");
|
||||||
|
|
||||||
|
b.Property<short>("Capacity")
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("capacity");
|
||||||
|
|
||||||
|
b.Property<string>("Model")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("model");
|
||||||
|
|
||||||
|
b.Property<string>("Number")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("number");
|
||||||
|
|
||||||
|
b.ToTable(t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_vehicles_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue("bus");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Train", b =>
|
||||||
|
{
|
||||||
|
b.HasBaseType("cuqmbr.TravelGuide.Domain.Entities.Vehicle");
|
||||||
|
|
||||||
|
b.Property<short>("Capacity")
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasColumnName("capacity");
|
||||||
|
|
||||||
|
b.Property<string>("Model")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("model");
|
||||||
|
|
||||||
|
b.Property<string>("Number")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnUpdateSometimes()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("number");
|
||||||
|
|
||||||
|
b.ToTable(t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_vehicles_vehicle_type", "vehicle_type IN ('bus', 'train', 'aircraft')");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.HasDiscriminator().HasValue("train");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Address", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.City", "City")
|
||||||
|
.WithMany("Addresses")
|
||||||
|
.HasForeignKey("CityId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_addresses_city_id");
|
||||||
|
|
||||||
|
b.Navigation("City");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.City", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Region", "Region")
|
||||||
|
.WithMany("Cities")
|
||||||
|
.HasForeignKey("RegionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_cities_region_id");
|
||||||
|
|
||||||
|
b.Navigation("Region");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Company", "Company")
|
||||||
|
.WithMany("Employees")
|
||||||
|
.HasForeignKey("CompanyId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_employees_company_id");
|
||||||
|
|
||||||
|
b.Navigation("Company");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.EmployeeDocument", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Employee", "Employee")
|
||||||
|
.WithMany("Documents")
|
||||||
|
.HasForeignKey("EmployeeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_employee_documents_employee_id");
|
||||||
|
|
||||||
|
b.Navigation("Employee");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Country", "Country")
|
||||||
|
.WithMany("Regions")
|
||||||
|
.HasForeignKey("CountryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_regions_country_id");
|
||||||
|
|
||||||
|
b.Navigation("Country");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.RouteAddress", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Address", "Address")
|
||||||
|
.WithMany("AddressRoutes")
|
||||||
|
.HasForeignKey("AddressId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_route_addresses_address_id");
|
||||||
|
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Route", "Route")
|
||||||
|
.WithMany("RouteAddresses")
|
||||||
|
.HasForeignKey("RouteId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_route_addresses_route_id");
|
||||||
|
|
||||||
|
b.Navigation("Address");
|
||||||
|
|
||||||
|
b.Navigation("Route");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.RouteAddressDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.RouteAddress", "RouteAddress")
|
||||||
|
.WithMany("Details")
|
||||||
|
.HasForeignKey("RouteAddressId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_route_address_details_route_address_id");
|
||||||
|
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.VehicleEnrollment", "VehicleEnrollment")
|
||||||
|
.WithMany("RouteAddressDetails")
|
||||||
|
.HasForeignKey("VehicleEnrollmentId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_route_address_details_vehicle_enrollment_id");
|
||||||
|
|
||||||
|
b.Navigation("RouteAddress");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollment");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Vehicle", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Company", "Company")
|
||||||
|
.WithMany("Vehicles")
|
||||||
|
.HasForeignKey("CompanyId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_vehicles_company_id");
|
||||||
|
|
||||||
|
b.Navigation("Company");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.VehicleEnrollment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Route", "Route")
|
||||||
|
.WithMany("VehicleEnrollments")
|
||||||
|
.HasForeignKey("RouteId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_vehicle_enrollments_route_id");
|
||||||
|
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Vehicle", "Vehicle")
|
||||||
|
.WithMany("Enrollments")
|
||||||
|
.HasForeignKey("VehicleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_vehicle_enrollments_vehicle_id");
|
||||||
|
|
||||||
|
b.Navigation("Route");
|
||||||
|
|
||||||
|
b.Navigation("Vehicle");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Address", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("AddressRoutes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.City", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Addresses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Company", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Employees");
|
||||||
|
|
||||||
|
b.Navigation("Vehicles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Country", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Regions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Documents");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Cities");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Route", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("RouteAddresses");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.RouteAddress", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Details");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Vehicle", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Enrollments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.VehicleEnrollment", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("RouteAddressDetails");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Persistence.PostgreSql.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Add_Employee_and_EmployeeDocument : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateSequence(
|
||||||
|
name: "employee_documents_id_sequence",
|
||||||
|
schema: "application");
|
||||||
|
|
||||||
|
migrationBuilder.CreateSequence(
|
||||||
|
name: "employees_id_sequence",
|
||||||
|
schema: "application");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "employees",
|
||||||
|
schema: "application",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<long>(type: "bigint", nullable: false, defaultValueSql: "nextval('application.employees_id_sequence')"),
|
||||||
|
first_name = table.Column<string>(type: "varchar(32)", nullable: false),
|
||||||
|
last_name = table.Column<string>(type: "varchar(32)", nullable: false),
|
||||||
|
patronymic = table.Column<string>(type: "varchar(32)", nullable: false),
|
||||||
|
sex = table.Column<string>(type: "varchar(32)", nullable: false),
|
||||||
|
birth_date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||||
|
company_id = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
uuid = table.Column<Guid>(type: "uuid", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_employees", x => x.id);
|
||||||
|
table.UniqueConstraint("altk_employees_uuid", x => x.uuid);
|
||||||
|
table.CheckConstraint("ck_employees_sex", "sex IN ('male', 'female')");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_employees_company_id",
|
||||||
|
column: x => x.company_id,
|
||||||
|
principalSchema: "application",
|
||||||
|
principalTable: "companies",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "employee_documents",
|
||||||
|
schema: "application",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<long>(type: "bigint", nullable: false, defaultValueSql: "nextval('application.employee_documents_id_sequence')"),
|
||||||
|
document_type = table.Column<string>(type: "varchar(64)", nullable: false),
|
||||||
|
information = table.Column<string>(type: "varchar(256)", nullable: false),
|
||||||
|
employee_id = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
uuid = table.Column<Guid>(type: "uuid", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_employee_documents", x => x.id);
|
||||||
|
table.UniqueConstraint("altk_employee_documents_uuid", x => x.uuid);
|
||||||
|
table.CheckConstraint("ck_employee_documents_document_type", "document_type IN ('passport')");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_employee_documents_employee_id",
|
||||||
|
column: x => x.employee_id,
|
||||||
|
principalSchema: "application",
|
||||||
|
principalTable: "employees",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_employee_documents_employee_id",
|
||||||
|
schema: "application",
|
||||||
|
table: "employee_documents",
|
||||||
|
column: "employee_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_employees_company_id",
|
||||||
|
schema: "application",
|
||||||
|
table: "employees",
|
||||||
|
column: "company_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "employee_documents",
|
||||||
|
schema: "application");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "employees",
|
||||||
|
schema: "application");
|
||||||
|
|
||||||
|
migrationBuilder.DropSequence(
|
||||||
|
name: "employee_documents_id_sequence",
|
||||||
|
schema: "application");
|
||||||
|
|
||||||
|
migrationBuilder.DropSequence(
|
||||||
|
name: "employees_id_sequence",
|
||||||
|
schema: "application");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,10 @@ namespace Persistence.PostgreSql.Migrations
|
|||||||
|
|
||||||
modelBuilder.HasSequence("countries_id_sequence");
|
modelBuilder.HasSequence("countries_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("employee_documents_id_sequence");
|
||||||
|
|
||||||
|
modelBuilder.HasSequence("employees_id_sequence");
|
||||||
|
|
||||||
modelBuilder.HasSequence("regions_id_sequence");
|
modelBuilder.HasSequence("regions_id_sequence");
|
||||||
|
|
||||||
modelBuilder.HasSequence("route_address_details_id_sequence");
|
modelBuilder.HasSequence("route_address_details_id_sequence");
|
||||||
@ -198,6 +202,106 @@ namespace Persistence.PostgreSql.Migrations
|
|||||||
b.ToTable("countries", "application");
|
b.ToTable("countries", "application");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.employees_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "employees_id_sequence");
|
||||||
|
|
||||||
|
b.Property<DateOnly>("BirthDate")
|
||||||
|
.HasColumnType("date")
|
||||||
|
.HasColumnName("birth_date");
|
||||||
|
|
||||||
|
b.Property<long>("CompanyId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("company_id");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("first_name");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("last_name");
|
||||||
|
|
||||||
|
b.Property<string>("Patronymic")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("patronymic");
|
||||||
|
|
||||||
|
b.Property<string>("Sex")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(32)")
|
||||||
|
.HasColumnName("sex");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_employees");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_employees_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("CompanyId")
|
||||||
|
.HasDatabaseName("ix_employees_company_id");
|
||||||
|
|
||||||
|
b.ToTable("employees", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_employees_sex", "sex IN ('male', 'female')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.EmployeeDocument", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id")
|
||||||
|
.HasDefaultValueSql("nextval('application.employee_documents_id_sequence')");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseSequence(b.Property<long>("Id"), "employee_documents_id_sequence");
|
||||||
|
|
||||||
|
b.Property<string>("DocumentType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(64)")
|
||||||
|
.HasColumnName("document_type");
|
||||||
|
|
||||||
|
b.Property<long>("EmployeeId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("employee_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("Guid")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Information")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(256)")
|
||||||
|
.HasColumnName("information");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_employee_documents");
|
||||||
|
|
||||||
|
b.HasAlternateKey("Guid")
|
||||||
|
.HasName("altk_employee_documents_uuid");
|
||||||
|
|
||||||
|
b.HasIndex("EmployeeId")
|
||||||
|
.HasDatabaseName("ix_employee_documents_employee_id");
|
||||||
|
|
||||||
|
b.ToTable("employee_documents", "application", t =>
|
||||||
|
{
|
||||||
|
t.HasCheckConstraint("ck_employee_documents_document_type", "document_type IN ('passport')");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
{
|
{
|
||||||
b.Property<long>("Id")
|
b.Property<long>("Id")
|
||||||
@ -564,6 +668,30 @@ namespace Persistence.PostgreSql.Migrations
|
|||||||
b.Navigation("Region");
|
b.Navigation("Region");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Company", "Company")
|
||||||
|
.WithMany("Employees")
|
||||||
|
.HasForeignKey("CompanyId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_employees_company_id");
|
||||||
|
|
||||||
|
b.Navigation("Company");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.EmployeeDocument", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Employee", "Employee")
|
||||||
|
.WithMany("Documents")
|
||||||
|
.HasForeignKey("EmployeeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_employee_documents_employee_id");
|
||||||
|
|
||||||
|
b.Navigation("Employee");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Country", "Country")
|
b.HasOne("cuqmbr.TravelGuide.Domain.Entities.Country", "Country")
|
||||||
@ -663,6 +791,8 @@ namespace Persistence.PostgreSql.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Company", b =>
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Company", b =>
|
||||||
{
|
{
|
||||||
|
b.Navigation("Employees");
|
||||||
|
|
||||||
b.Navigation("Vehicles");
|
b.Navigation("Vehicles");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -671,6 +801,11 @@ namespace Persistence.PostgreSql.Migrations
|
|||||||
b.Navigation("Regions");
|
b.Navigation("Regions");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Employee", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Documents");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
modelBuilder.Entity("cuqmbr.TravelGuide.Domain.Entities.Region", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Cities");
|
b.Navigation("Cities");
|
||||||
|
@ -44,6 +44,16 @@ public class PostgreSqlDbContext : DbContext
|
|||||||
.HaveColumnType("varchar(8)")
|
.HaveColumnType("varchar(8)")
|
||||||
.HaveConversion<CurrencyConverter>();
|
.HaveConversion<CurrencyConverter>();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Properties<DocumentType>()
|
||||||
|
.HaveColumnType("varchar(64)")
|
||||||
|
.HaveConversion<DocumentTypeConverter>();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Properties<Sex>()
|
||||||
|
.HaveColumnType("varchar(32)")
|
||||||
|
.HaveConversion<SexConverter>();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.Properties<DateTimeOffset>()
|
.Properties<DateTimeOffset>()
|
||||||
.HaveConversion<DateTimeOffsetConverter>();
|
.HaveConversion<DateTimeOffsetConverter>();
|
||||||
|
@ -27,6 +27,7 @@ public sealed class PostgreSqlUnitOfWork : UnitOfWork
|
|||||||
RouteAddressRepository =
|
RouteAddressRepository =
|
||||||
new PostgreSqlRouteAddressRepository(_dbContext);
|
new PostgreSqlRouteAddressRepository(_dbContext);
|
||||||
CompanyRepository = new PostgreSqlCompanyRepository(_dbContext);
|
CompanyRepository = new PostgreSqlCompanyRepository(_dbContext);
|
||||||
|
EmployeeRepository = new PostgreSqlEmployeeRepository(_dbContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CountryRepository CountryRepository { get; init; }
|
public CountryRepository CountryRepository { get; init; }
|
||||||
@ -53,6 +54,8 @@ public sealed class PostgreSqlUnitOfWork : UnitOfWork
|
|||||||
|
|
||||||
public CompanyRepository CompanyRepository { get; init; }
|
public CompanyRepository CompanyRepository { get; init; }
|
||||||
|
|
||||||
|
public EmployeeRepository EmployeeRepository { get; init; }
|
||||||
|
|
||||||
public int Save()
|
public int Save()
|
||||||
{
|
{
|
||||||
return _dbContext.SaveChanges();
|
return _dbContext.SaveChanges();
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence.Repositories;
|
||||||
|
using cuqmbr.TravelGuide.Domain.Entities;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.PostgreSql.Repositories;
|
||||||
|
|
||||||
|
public sealed class PostgreSqlEmployeeRepository :
|
||||||
|
PostgreSqlBaseRepository<Employee>, EmployeeRepository
|
||||||
|
{
|
||||||
|
public PostgreSqlEmployeeRepository(PostgreSqlDbContext dbContext)
|
||||||
|
: base(dbContext) { }
|
||||||
|
}
|
13
src/Persistence/TypeConverters/DocumentTypeConverter.cs
Normal file
13
src/Persistence/TypeConverters/DocumentTypeConverter.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.TypeConverters;
|
||||||
|
|
||||||
|
public class DocumentTypeConverter : ValueConverter<DocumentType, string>
|
||||||
|
{
|
||||||
|
public DocumentTypeConverter()
|
||||||
|
: base(
|
||||||
|
v => v.Name,
|
||||||
|
v => DocumentType.FromName(v))
|
||||||
|
{ }
|
||||||
|
}
|
13
src/Persistence/TypeConverters/SexConverter.cs
Normal file
13
src/Persistence/TypeConverters/SexConverter.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using cuqmbr.TravelGuide.Domain.Enums;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
namespace cuqmbr.TravelGuide.Persistence.TypeConverters;
|
||||||
|
|
||||||
|
public class SexConverter : ValueConverter<Sex, string>
|
||||||
|
{
|
||||||
|
public SexConverter()
|
||||||
|
: base(
|
||||||
|
v => v.Name,
|
||||||
|
v => Sex.FromName(v))
|
||||||
|
{ }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user