Compare commits
7 Commits
3ebd0c3a2c
...
5fc9308ada
Author | SHA1 | Date | |
---|---|---|---|
5fc9308ada | |||
674130c52a | |||
5982fa7285 | |||
f4611f029f | |||
74dc7ceff3 | |||
b1aceac750 | |||
5ee8c9c5df |
@ -9,7 +9,7 @@ public class AddAddressCommandValidator : AbstractValidator<AddAddressCommand>
|
||||
{
|
||||
public AddAddressCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Name)
|
||||
.NotEmpty()
|
||||
|
@ -8,7 +8,7 @@ public class UpdateAddressCommandValidator : AbstractValidator<UpdateAddressComm
|
||||
{
|
||||
public UpdateAddressCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
|
@ -8,7 +8,7 @@ public class GetAddressesPageQueryValidator : AbstractValidator<GetAddressesPage
|
||||
{
|
||||
public GetAddressesPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
|
@ -13,11 +13,16 @@ public sealed class AircraftDto : IMapFrom<Aircraft>
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
|
||||
public void Mapping(MappingProfile profile)
|
||||
{
|
||||
profile.CreateMap<Aircraft, AircraftDto>()
|
||||
.ForMember(
|
||||
d => d.Uuid,
|
||||
opt => opt.MapFrom(s => s.Guid));
|
||||
opt => opt.MapFrom(s => s.Guid))
|
||||
.ForMember(
|
||||
d => d.CompanyUuid,
|
||||
opt => opt.MapFrom(s => s.Company.Guid));
|
||||
}
|
||||
}
|
||||
|
@ -9,4 +9,6 @@ public record AddAircraftCommand : IRequest<AircraftDto>
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyGuid { get; set; }
|
||||
}
|
||||
|
@ -33,11 +33,23 @@ public class AddAircraftCommandHandler :
|
||||
"Aircraft with given number already exists.");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
|
||||
entity = new Aircraft()
|
||||
{
|
||||
Number = request.Number,
|
||||
Model = request.Model,
|
||||
Capacity = request.Capacity
|
||||
Capacity = request.Capacity,
|
||||
CompanyId = parentEntity.Id,
|
||||
Company = parentEntity
|
||||
};
|
||||
|
||||
entity = await _unitOfWork.AircraftRepository.AddOneAsync(
|
||||
|
@ -8,7 +8,7 @@ public class AddAircraftCommandValidator : AbstractValidator<AddAircraftCommand>
|
||||
{
|
||||
public AddAircraftCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Number)
|
||||
.NotEmpty()
|
||||
@ -33,5 +33,9 @@ public class AddAircraftCommandValidator : AbstractValidator<AddAircraftCommand>
|
||||
RuleFor(v => v.Capacity)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.CompanyGuid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,6 @@ public record UpdateAircraftCommand : IRequest<AircraftDto>
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyGuid { get; set; }
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class UpdateAircraftCommandHandler :
|
||||
}
|
||||
|
||||
var duplicateEntity = await _unitOfWork.AircraftRepository.GetOneAsync(
|
||||
e => e.Number == request.Number,
|
||||
e => e.Number == request.Number && e.Guid != request.Guid,
|
||||
cancellationToken);
|
||||
|
||||
if (duplicateEntity != null)
|
||||
@ -41,9 +41,20 @@ public class UpdateAircraftCommandHandler :
|
||||
"Aircraft with given number already exists.");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
entity.Number = request.Number;
|
||||
entity.Model = request.Model;
|
||||
entity.Capacity = request.Capacity;
|
||||
entity.CompanyId = parentEntity.Id;
|
||||
entity.Company = parentEntity;
|
||||
|
||||
entity = await _unitOfWork.AircraftRepository.UpdateOneAsync(
|
||||
entity, cancellationToken);
|
||||
|
@ -8,7 +8,7 @@ public class UpdateAircraftCommandValidator : AbstractValidator<UpdateAircraftCo
|
||||
{
|
||||
public UpdateAircraftCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
@ -37,5 +37,9 @@ public class UpdateAircraftCommandValidator : AbstractValidator<UpdateAircraftCo
|
||||
RuleFor(v => v.Capacity)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.CompanyGuid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ public class GetAircraftQueryHandler :
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.AircraftRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
e => e.Guid == request.Guid, e => e.Company,
|
||||
cancellationToken);
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
|
@ -13,11 +13,9 @@ public record GetAircraftsPageQuery : IRequest<PaginatedList<AircraftDto>>
|
||||
|
||||
public string Sort { get; set; } = String.Empty;
|
||||
|
||||
public string? Number { get; set; }
|
||||
public Guid? CompanyGuid { get; set; }
|
||||
|
||||
public string? Model { get; set; }
|
||||
public short? CapacityGreaterThanOrEqualTo { get; set; }
|
||||
|
||||
public short? CapacityGreaterOrEqualThan { get; set; }
|
||||
|
||||
public short? CapacityLessOrEqualThan { get; set; }
|
||||
public short? CapacityLessThanOrEqualTo { get; set; }
|
||||
}
|
||||
|
@ -28,12 +28,16 @@ public class GetAircraftsPageQueryHandler :
|
||||
e =>
|
||||
(e.Number.ToLower().Contains(request.Search.ToLower()) ||
|
||||
e.Model.ToLower().Contains(request.Search.ToLower())) &&
|
||||
(request.CapacityGreaterOrEqualThan != null
|
||||
? e.Capacity >= request.CapacityGreaterOrEqualThan
|
||||
(request.CompanyGuid != null
|
||||
? e.Company.Guid == request.CompanyGuid
|
||||
: true) &&
|
||||
(request.CapacityLessOrEqualThan != null
|
||||
? e.Capacity <= request.CapacityLessOrEqualThan
|
||||
(request.CapacityGreaterThanOrEqualTo != null
|
||||
? e.Capacity >= request.CapacityGreaterThanOrEqualTo
|
||||
: true) &&
|
||||
(request.CapacityLessThanOrEqualTo != null
|
||||
? e.Capacity <= request.CapacityLessThanOrEqualTo
|
||||
: true),
|
||||
e => e.Company,
|
||||
request.PageNumber, request.PageSize,
|
||||
cancellationToken);
|
||||
|
||||
|
@ -8,7 +8,7 @@ public class GetAircraftsPageQueryValidator : AbstractValidator<GetAircraftsPage
|
||||
{
|
||||
public GetAircraftsPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
|
@ -7,4 +7,6 @@ public sealed class AddAircraftViewModel
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
}
|
||||
|
@ -2,14 +2,12 @@ namespace cuqmbr.TravelGuide.Application.Aircrafts.ViewModels;
|
||||
|
||||
public sealed class GetAircraftsPageFilterViewModel
|
||||
{
|
||||
public string? Number { get; set; }
|
||||
|
||||
public string? Model { get; set; }
|
||||
public Guid? CompanyUuid { get; set; }
|
||||
|
||||
// TODO: Consider adding strict equals rule although it is not
|
||||
// necessarily needed to filter with exact capacity
|
||||
|
||||
public short? CapacityGreaterOrEqualThan { get; set; }
|
||||
public short? CapacityGreaterThanOrEqualTo { get; set; }
|
||||
|
||||
public short? CapacityLessOrEqualThan { get; set; }
|
||||
public short? CapacityLessThanOrEqualTo { get; set; }
|
||||
}
|
||||
|
@ -7,4 +7,6 @@ public sealed class UpdateAircraftViewModel
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
}
|
||||
|
@ -13,11 +13,16 @@ public sealed class BusDto : IMapFrom<Bus>
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
|
||||
public void Mapping(MappingProfile profile)
|
||||
{
|
||||
profile.CreateMap<Bus, BusDto>()
|
||||
.ForMember(
|
||||
d => d.Uuid,
|
||||
opt => opt.MapFrom(s => s.Guid));
|
||||
opt => opt.MapFrom(s => s.Guid))
|
||||
.ForMember(
|
||||
d => d.CompanyUuid,
|
||||
opt => opt.MapFrom(s => s.Company.Guid));
|
||||
}
|
||||
}
|
||||
|
@ -9,4 +9,6 @@ public record AddBusCommand : IRequest<BusDto>
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyGuid { get; set; }
|
||||
}
|
||||
|
@ -33,11 +33,22 @@ public class AddBusCommandHandler :
|
||||
"Bus with given number already exists.");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
entity = new Bus()
|
||||
{
|
||||
Number = request.Number,
|
||||
Model = request.Model,
|
||||
Capacity = request.Capacity
|
||||
Capacity = request.Capacity,
|
||||
CompanyId = parentEntity.Id,
|
||||
Company = parentEntity
|
||||
};
|
||||
|
||||
entity = await _unitOfWork.BusRepository.AddOneAsync(
|
||||
|
@ -8,7 +8,7 @@ public class AddBusCommandValidator : AbstractValidator<AddBusCommand>
|
||||
{
|
||||
public AddBusCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Number)
|
||||
.NotEmpty()
|
||||
@ -33,5 +33,9 @@ public class AddBusCommandValidator : AbstractValidator<AddBusCommand>
|
||||
RuleFor(v => v.Capacity)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.CompanyGuid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,6 @@ public record UpdateBusCommand : IRequest<BusDto>
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyGuid { get; set; }
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class UpdateBusCommandHandler :
|
||||
}
|
||||
|
||||
var duplicateEntity = await _unitOfWork.BusRepository.GetOneAsync(
|
||||
e => e.Number == request.Number,
|
||||
e => e.Number == request.Number && e.Guid != request.Guid,
|
||||
cancellationToken);
|
||||
|
||||
if (duplicateEntity != null)
|
||||
@ -41,9 +41,20 @@ public class UpdateBusCommandHandler :
|
||||
"Bus with given number already exists.");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
entity.Number = request.Number;
|
||||
entity.Model = request.Model;
|
||||
entity.Capacity = request.Capacity;
|
||||
entity.CompanyId = parentEntity.Id;
|
||||
entity.Company = parentEntity;
|
||||
|
||||
entity = await _unitOfWork.BusRepository.UpdateOneAsync(
|
||||
entity, cancellationToken);
|
||||
|
@ -8,7 +8,7 @@ public class UpdateBusCommandValidator : AbstractValidator<UpdateBusCommand>
|
||||
{
|
||||
public UpdateBusCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
@ -37,5 +37,9 @@ public class UpdateBusCommandValidator : AbstractValidator<UpdateBusCommand>
|
||||
RuleFor(v => v.Capacity)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.CompanyGuid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ public class GetBusQueryHandler :
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.BusRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
e => e.Guid == request.Guid, e => e.Company,
|
||||
cancellationToken);
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
|
@ -13,11 +13,9 @@ public record GetBusesPageQuery : IRequest<PaginatedList<BusDto>>
|
||||
|
||||
public string Sort { get; set; } = String.Empty;
|
||||
|
||||
public string? Number { get; set; }
|
||||
public Guid? CompanyGuid { get; set; }
|
||||
|
||||
public string? Model { get; set; }
|
||||
public short? CapacityGreaterThanOrEqualTo { get; set; }
|
||||
|
||||
public short? CapacityGreaterOrEqualThan { get; set; }
|
||||
|
||||
public short? CapacityLessOrEqualThan { get; set; }
|
||||
public short? CapacityLessThanOrEqualTo { get; set; }
|
||||
}
|
||||
|
@ -28,12 +28,16 @@ public class GetBusesPageQueryHandler :
|
||||
e =>
|
||||
(e.Number.ToLower().Contains(request.Search.ToLower()) ||
|
||||
e.Model.ToLower().Contains(request.Search.ToLower())) &&
|
||||
(request.CapacityGreaterOrEqualThan != null
|
||||
? e.Capacity >= request.CapacityGreaterOrEqualThan
|
||||
(request.CompanyGuid != null
|
||||
? e.Company.Guid == request.CompanyGuid
|
||||
: true) &&
|
||||
(request.CapacityLessOrEqualThan != null
|
||||
? e.Capacity <= request.CapacityLessOrEqualThan
|
||||
(request.CapacityGreaterThanOrEqualTo != null
|
||||
? e.Capacity >= request.CapacityGreaterThanOrEqualTo
|
||||
: true) &&
|
||||
(request.CapacityLessThanOrEqualTo != null
|
||||
? e.Capacity <= request.CapacityLessThanOrEqualTo
|
||||
: true),
|
||||
e => e.Company,
|
||||
request.PageNumber, request.PageSize,
|
||||
cancellationToken);
|
||||
|
||||
|
@ -8,7 +8,7 @@ public class GetBusesPageQueryValidator : AbstractValidator<GetBusesPageQuery>
|
||||
{
|
||||
public GetBusesPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
|
@ -7,4 +7,6 @@ public sealed class AddBusViewModel
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
}
|
||||
|
@ -2,14 +2,9 @@ namespace cuqmbr.TravelGuide.Application.Buses.ViewModels;
|
||||
|
||||
public sealed class GetBusesPageFilterViewModel
|
||||
{
|
||||
public string? Number { get; set; }
|
||||
public Guid? CompanyUuid { get; set; }
|
||||
|
||||
public string? Model { get; set; }
|
||||
public short? CapacityGreaterThanOrEqualTo { get; set; }
|
||||
|
||||
// TODO: Consider adding strict equals rule although it is not
|
||||
// necessarily needed to filter with exact capacity
|
||||
|
||||
public short? CapacityGreaterOrEqualThan { get; set; }
|
||||
|
||||
public short? CapacityLessOrEqualThan { get; set; }
|
||||
public short? CapacityLessThanOrEqualTo { get; set; }
|
||||
}
|
||||
|
@ -7,4 +7,6 @@ public sealed class UpdateBusViewModel
|
||||
public string Model { get; set; }
|
||||
|
||||
public short Capacity { get; set; }
|
||||
|
||||
public Guid CompanyUuid { get; set; }
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public class AddCityCommandValidator : AbstractValidator<AddCityCommand>
|
||||
{
|
||||
public AddCityCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Name)
|
||||
.NotEmpty()
|
||||
|
@ -8,7 +8,7 @@ public class UpdateCityCommandValidator : AbstractValidator<UpdateCityCommand>
|
||||
{
|
||||
public UpdateCityCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
|
@ -8,7 +8,7 @@ public class GetCitiesPageQueryValidator : AbstractValidator<GetCitiesPageQuery>
|
||||
{
|
||||
public GetCitiesPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
|
55
src/Application/Common/FluentValidation/CustomValidators.cs
Normal file
55
src/Application/Common/FluentValidation/CustomValidators.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
|
||||
public static class CustomValidators
|
||||
{
|
||||
// According to RFC 5321.
|
||||
public static IRuleBuilderOptions<T, string> IsEmail<T>(
|
||||
this IRuleBuilder<T, string> ruleBuilder)
|
||||
{
|
||||
return
|
||||
ruleBuilder
|
||||
.Matches(@"^[\w\.-]{1,64}@[\w\.-]{1,251}\.\w{2,4}$");
|
||||
}
|
||||
|
||||
// According to ITU-T E.164, no spaces.
|
||||
public static IRuleBuilderOptions<T, string> IsPhoneNumber<T>(
|
||||
this IRuleBuilder<T, string> ruleBuilder)
|
||||
{
|
||||
return
|
||||
ruleBuilder
|
||||
.Matches(@"^\+[0-9]{7,15}$");
|
||||
}
|
||||
|
||||
public static IRuleBuilderOptions<T, ICollection<TSource>>
|
||||
IsUnique<T, TSource, TResult>(
|
||||
this IRuleBuilder<T, ICollection<TSource>> ruleBuilder,
|
||||
Func<TSource, TResult> selector)
|
||||
{
|
||||
if (selector == null)
|
||||
{
|
||||
throw new ArgumentNullException(
|
||||
nameof(selector),
|
||||
"Cannot pass a null selector.");
|
||||
}
|
||||
|
||||
return
|
||||
ruleBuilder
|
||||
.Must(x => x.IsDistinct(selector));
|
||||
}
|
||||
|
||||
public static bool IsDistinct<TSource, TResult>(
|
||||
this IEnumerable<TSource> elements, Func<TSource, TResult> selector)
|
||||
{
|
||||
var hashSet = new HashSet<TResult>();
|
||||
foreach (var element in elements.Select(selector))
|
||||
{
|
||||
if (!hashSet.Contains(element))
|
||||
hashSet.Add(element);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface CompanyRepository : BaseRepository<Company> { }
|
@ -0,0 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface EmployeeRepository : BaseRepository<Employee> { }
|
@ -0,0 +1,7 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface RouteAddressDetailRepository :
|
||||
BaseRepository<RouteAddressDetail> { }
|
@ -0,0 +1,7 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface RouteAddressRepository :
|
||||
BaseRepository<RouteAddress> { }
|
@ -0,0 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface TicketGroupRepository : BaseRepository<TicketGroup> { }
|
@ -0,0 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface TicketRepository : BaseRepository<Ticket> { }
|
@ -0,0 +1,7 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface VehicleEnrollmentRepository :
|
||||
BaseRepository<VehicleEnrollment> { }
|
@ -22,6 +22,20 @@ public interface UnitOfWork : IDisposable
|
||||
|
||||
TrainRepository TrainRepository { get; }
|
||||
|
||||
VehicleEnrollmentRepository VehicleEnrollmentRepository { get; }
|
||||
|
||||
RouteAddressRepository RouteAddressRepository { get; }
|
||||
|
||||
CompanyRepository CompanyRepository { get; }
|
||||
|
||||
EmployeeRepository EmployeeRepository { get; }
|
||||
|
||||
TicketGroupRepository TicketGroupRepository { get; }
|
||||
|
||||
TicketRepository TicketRepository { get; }
|
||||
|
||||
RouteAddressDetailRepository RouteAddressDetailRepository { get; }
|
||||
|
||||
int Save();
|
||||
|
||||
Task<int> SaveAsync(CancellationToken cancellationToken);
|
||||
|
@ -0,0 +1,12 @@
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface CurrencyConverterService
|
||||
{
|
||||
Task<decimal> ConvertAsync(decimal amount, Currency from, Currency to,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<decimal> ConvertAsync(decimal amount, Currency from, Currency to,
|
||||
DateTimeOffset time, CancellationToken cancellationToken);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface SessionCurrencyService
|
||||
{
|
||||
public Currency Currency { get; }
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface TimeZoneService
|
||||
public interface SessionTimeZoneService
|
||||
{
|
||||
public TimeZoneInfo TimeZone { get; }
|
||||
}
|
@ -2,7 +2,7 @@ using System.Globalization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface CultureService
|
||||
public interface SessionCultureService
|
||||
{
|
||||
public CultureInfo Culture { get; }
|
||||
}
|
@ -6,9 +6,9 @@ namespace cuqmbr.TravelGuide.Application.Common.Mappings.Resolvers;
|
||||
public class DateTimeOffsetToLocalResolver :
|
||||
IMemberValueResolver<object, object, DateTimeOffset, DateTimeOffset>
|
||||
{
|
||||
private readonly TimeZoneService _timeZoneService;
|
||||
private readonly SessionTimeZoneService _timeZoneService;
|
||||
|
||||
public DateTimeOffsetToLocalResolver(TimeZoneService timeZoneService)
|
||||
public DateTimeOffsetToLocalResolver(SessionTimeZoneService timeZoneService)
|
||||
{
|
||||
_timeZoneService = timeZoneService;
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.AddCompany;
|
||||
|
||||
public record AddCompanyCommand : IRequest<CompanyDto>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string LegalAddress { get; set; }
|
||||
|
||||
public string ContactEmail { get; set; }
|
||||
|
||||
public string ContactPhoneNumber { 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.Companies.Commands.AddCompany;
|
||||
|
||||
public class AddCompanyCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<AddCompanyCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public AddCompanyCommandAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(AddCompanyCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.AddCompany;
|
||||
|
||||
public class AddCompanyCommandHandler :
|
||||
IRequestHandler<AddCompanyCommand, CompanyDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public AddCompanyCommandHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<CompanyDto> Handle(
|
||||
AddCompanyCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||
e => e.Name == request.Name, cancellationToken);
|
||||
|
||||
if (entity != null)
|
||||
{
|
||||
throw new DuplicateEntityException(
|
||||
"Company with given name already exists.");
|
||||
}
|
||||
|
||||
entity = new Company()
|
||||
{
|
||||
Name = request.Name,
|
||||
LegalAddress = request.LegalAddress,
|
||||
ContactEmail = request.ContactEmail,
|
||||
ContactPhoneNumber = request.ContactPhoneNumber
|
||||
};
|
||||
|
||||
entity = await _unitOfWork.CompanyRepository.AddOneAsync(
|
||||
entity, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return _mapper.Map<CompanyDto>(entity);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.AddCompany;
|
||||
|
||||
public class AddCompanyCommandValidator : AbstractValidator<AddCompanyCommand>
|
||||
{
|
||||
public AddCompanyCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Name)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
|
||||
RuleFor(v => v.LegalAddress)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MaximumLength(256)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
256));
|
||||
|
||||
RuleFor(v => v.ContactEmail)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.IsEmail()
|
||||
.WithMessage(localizer["FluentValidation.IsEmail"])
|
||||
.MaximumLength(256)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
256));
|
||||
|
||||
RuleFor(v => v.ContactPhoneNumber)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.IsPhoneNumber()
|
||||
.WithMessage(localizer["FluentValidation.IsPhoneNumber"])
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.DeleteCompany;
|
||||
|
||||
public record DeleteCompanyCommand : 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.Companies.Commands.DeleteCompany;
|
||||
|
||||
public class DeleteCompanyCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<DeleteCompanyCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public DeleteCompanyCommandAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(DeleteCompanyCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.DeleteCompany;
|
||||
|
||||
public class DeleteCompanyCommandHandler : IRequestHandler<DeleteCompanyCommand>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteCompanyCommandHandler(UnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task Handle(
|
||||
DeleteCompanyCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _unitOfWork.CompanyRepository.DeleteOneAsync(
|
||||
entity, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.DeleteCompany;
|
||||
|
||||
public class DeleteCompanyCommandValidator : AbstractValidator<DeleteCompanyCommand>
|
||||
{
|
||||
public DeleteCompanyCommandValidator(IStringLocalizer localizer)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.UpdateCompany;
|
||||
|
||||
public record UpdateCompanyCommand : IRequest<CompanyDto>
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string LegalAddress { get; set; }
|
||||
|
||||
public string ContactEmail { get; set; }
|
||||
|
||||
public string ContactPhoneNumber { 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.Companies.Commands.UpdateCompany;
|
||||
|
||||
public class UpdateCompanyCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<UpdateCompanyCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public UpdateCompanyCommandAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(UpdateCompanyCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.UpdateCompany;
|
||||
|
||||
public class UpdateCompanyCommandHandler :
|
||||
IRequestHandler<UpdateCompanyCommand, CompanyDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public UpdateCompanyCommandHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<CompanyDto> Handle(
|
||||
UpdateCompanyCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
entity.Name = request.Name;
|
||||
entity.LegalAddress = request.LegalAddress;
|
||||
entity.ContactEmail = request.ContactEmail;
|
||||
entity.ContactPhoneNumber = request.ContactPhoneNumber;
|
||||
|
||||
entity = await _unitOfWork.CompanyRepository.UpdateOneAsync(
|
||||
entity, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return _mapper.Map<CompanyDto>(entity);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Commands.UpdateCompany;
|
||||
|
||||
public class UpdateCompanyCommandValidator : AbstractValidator<UpdateCompanyCommand>
|
||||
{
|
||||
public UpdateCompanyCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.Name)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
|
||||
RuleFor(v => v.LegalAddress)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MaximumLength(256)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
256));
|
||||
|
||||
RuleFor(v => v.ContactEmail)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.IsEmail()
|
||||
.WithMessage(localizer["FluentValidation.IsEmail"])
|
||||
.MaximumLength(256)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
256));
|
||||
|
||||
RuleFor(v => v.ContactPhoneNumber)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.IsPhoneNumber()
|
||||
.WithMessage(localizer["FluentValidation.IsPhoneNumber"])
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
}
|
||||
}
|
25
src/Application/Companies/CompanyDto.cs
Normal file
25
src/Application/Companies/CompanyDto.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Mappings;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies;
|
||||
|
||||
public sealed class CompanyDto : IMapFrom<Company>
|
||||
{
|
||||
public Guid Uuid { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string LegalAddress { get; set; }
|
||||
|
||||
public string ContactEmail { get; set; }
|
||||
|
||||
public string ContactPhoneNumber { get; set; }
|
||||
|
||||
public void Mapping(MappingProfile profile)
|
||||
{
|
||||
profile.CreateMap<Company, CompanyDto>()
|
||||
.ForMember(
|
||||
d => d.Uuid,
|
||||
opt => opt.MapFrom(s => s.Guid));
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Queries.GetCompaniesPage;
|
||||
|
||||
public record GetCompaniesPageQuery : IRequest<PaginatedList<CompanyDto>>
|
||||
{
|
||||
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;
|
||||
}
|
@ -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.Companies.Queries.GetCompaniesPage;
|
||||
|
||||
public class GetCompaniesPageQueryAuthorizer :
|
||||
AbstractRequestAuthorizer<GetCompaniesPageQuery>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public GetCompaniesPageQueryAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(GetCompaniesPageQuery request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
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.Companies.Queries.GetCompaniesPage;
|
||||
|
||||
public class GetCompaniesPageQueryHandler :
|
||||
IRequestHandler<GetCompaniesPageQuery, PaginatedList<CompanyDto>>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetCompaniesPageQueryHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<PaginatedList<CompanyDto>> Handle(
|
||||
GetCompaniesPageQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var paginatedList = await _unitOfWork.CompanyRepository.GetPageAsync(
|
||||
e =>
|
||||
e.Name.ToLower().Contains(request.Search.ToLower()) ||
|
||||
e.LegalAddress.ToLower().Contains(request.Search.ToLower()) ||
|
||||
e.ContactEmail.ToLower().Contains(request.Search.ToLower()) ||
|
||||
e.ContactPhoneNumber.ToLower().Contains(request.Search.ToLower()),
|
||||
request.PageNumber, request.PageSize,
|
||||
cancellationToken);
|
||||
|
||||
var mappedItems = _mapper
|
||||
.ProjectTo<CompanyDto>(paginatedList.Items.AsQueryable());
|
||||
|
||||
mappedItems = QueryableExtension<CompanyDto>
|
||||
.ApplySort(mappedItems, request.Sort);
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return new PaginatedList<CompanyDto>(
|
||||
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.Companies.Queries.GetCompaniesPage;
|
||||
|
||||
public class GetCompaniesPageQueryValidator : AbstractValidator<GetCompaniesPageQuery>
|
||||
{
|
||||
public GetCompaniesPageQueryValidator(
|
||||
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));
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Queries.GetCompany;
|
||||
|
||||
public record GetCompanyQuery : IRequest<CompanyDto>
|
||||
{
|
||||
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.Companies.Queries.GetCompany;
|
||||
|
||||
public class GetCompanyQueryAuthorizer :
|
||||
AbstractRequestAuthorizer<GetCompanyQuery>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public GetCompanyQueryAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(GetCompanyQuery request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Queries.GetCompany;
|
||||
|
||||
public class GetCompanyQueryHandler :
|
||||
IRequestHandler<GetCompanyQuery, CompanyDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetCompanyQueryHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<CompanyDto> Handle(
|
||||
GetCompanyQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var entity = await _unitOfWork.CompanyRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return _mapper.Map<CompanyDto>(entity);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.Queries.GetCompany;
|
||||
|
||||
public class GetCompanyQueryValidator : AbstractValidator<GetCompanyQuery>
|
||||
{
|
||||
public GetCompanyQueryValidator(IStringLocalizer localizer)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
12
src/Application/Companies/ViewModels/AddCompanyViewModel.cs
Normal file
12
src/Application/Companies/ViewModels/AddCompanyViewModel.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.ViewModels;
|
||||
|
||||
public sealed class AddCompanyViewModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string LegalAddress { get; set; }
|
||||
|
||||
public string ContactEmail { get; set; }
|
||||
|
||||
public string ContactPhoneNumber { get; set; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace cuqmbr.TravelGuide.Application.Companies.ViewModels;
|
||||
|
||||
public sealed class UpdateCompanyViewModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string LegalAddress { get; set; }
|
||||
|
||||
public string ContactEmail { get; set; }
|
||||
|
||||
public string ContactPhoneNumber { get; set; }
|
||||
}
|
@ -8,7 +8,7 @@ public class AddCountryCommandValidator : AbstractValidator<AddCountryCommand>
|
||||
{
|
||||
public AddCountryCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Name)
|
||||
.NotEmpty()
|
||||
|
@ -8,7 +8,7 @@ public class UpdateCountryCommandValidator : AbstractValidator<UpdateCountryComm
|
||||
{
|
||||
public UpdateCountryCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
|
@ -9,7 +9,7 @@ public class GetCountriesPageQueryValidator :
|
||||
{
|
||||
public GetCountriesPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
CultureService cultureService)
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
|
@ -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; }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user