Commit 142bdb84 authored by hasan khaddour's avatar hasan khaddour

Add Domain Models (Entities and Aggregate )

parent 804e6ccf
using MediatR; using FluentResults;
using FluentValidation;
using MediatR;
using PSManagement.Application.Common.Exceptions; using PSManagement.Application.Common.Exceptions;
using PSManagement.SharedKernel.CQRS.Command;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
...@@ -10,45 +13,41 @@ using ValidationException = PSManagement.Application.Common.Exceptions.Validatio ...@@ -10,45 +13,41 @@ using ValidationException = PSManagement.Application.Common.Exceptions.Validatio
namespace PSManagement.Application.Behaviors.ValidationBehavior namespace PSManagement.Application.Behaviors.ValidationBehavior
{ {
public sealed class ValidationBehavior<TRequest, TResponse> //: IPipelineBehavior<TRequest, TResponse>
// where TRequest : class, ICommand<TResponse>
{
//private readonly IEnumerable<IValidator<TRequest>> _validators;
//public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators) => _validators = validators; public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse> where TResponse : ResultBase
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
//public async Task<TResponse> Handle( public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators = null)
// TRequest request, {
// CancellationToken cancellationToken, _validators = validators;
// RequestHandlerDelegate<TResponse> next) }
//{
// if (!_validators.Any())
// {
// return await next();
// }
// var context = new ValidationContext<TRequest>(request); public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext<TRequest>(request);
if (_validators is null) {
// var errorsDictionary = _validators return await next();
// .Select(x => x.Validate(context)) }
// .SelectMany(x => x.Errors) var failures = _validators
// .Where(x => x != null) .Select(v => v.Validate(context))
// .GroupBy( .SelectMany(result => result.Errors)
// x => x.PropertyName, .Where(f => f != null)
// x => x.ErrorMessage, .ToList();
// (propertyName, errorMessages) => new
// {
// Key = propertyName,
// Values = errorMessages.Distinct().ToArray()
// })
// .ToDictionary(x => x.Key, x => x.Values);
// if (errorsDictionary.Any()) if (failures.Count != 0)
// { {
// throw new ValidationException(errorsDictionary); var result =Result.Fail("validation Error.");
// } foreach (var failure in failures)
{
result.Reasons.Add(new Error(failure.ErrorMessage));
}
return (dynamic)result;
}
// return await next(); return await next();
//} }
} }
} }
//using PSManagement.SharedKernel.Utilities; 
using FluentResults; using FluentResults;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
......
...@@ -6,7 +6,7 @@ namespace PSManagement.Application.Customers.Common ...@@ -6,7 +6,7 @@ namespace PSManagement.Application.Customers.Common
public class ContactInfoDTO public class ContactInfoDTO
{ {
public String ConatctValue { get; set; } public String ConatctValue { get; set; }
public String ContactTpe { get; set; } public String ContactType { get; set; }
} }
} }
\ No newline at end of file
...@@ -27,7 +27,7 @@ namespace PSManagement.Application.Customers.UseCases.Commands.AddContactInfo ...@@ -27,7 +27,7 @@ namespace PSManagement.Application.Customers.UseCases.Commands.AddContactInfo
return Result.Fail(CustomerErrors.InvalidEntryError); return Result.Fail(CustomerErrors.InvalidEntryError);
} }
ContactInfo contact = new ContactInfo(request.ContactValue,request.ContactType); ContactInfo contact = new (request.ContactValue,request.ContactType);
customer.AddContactInfo(contact); customer.AddContactInfo(contact);
await _customersRepository.UpdateAsync(customer); await _customersRepository.UpdateAsync(customer);
return Result.Ok(); return Result.Ok();
......
using FluentResults; 
using FluentResults;
using PSManagement.Application.Customers.Common; using PSManagement.Application.Customers.Common;
using PSManagement.Domain.Customers.Aggregate; using PSManagement.Domain.Customers.Aggregate;
using PSManagement.Domain.Customers.ValueObjects; using PSManagement.Domain.Customers.ValueObjects;
......
using System; using FluentValidation;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
...@@ -6,7 +7,12 @@ using System.Threading.Tasks; ...@@ -6,7 +7,12 @@ using System.Threading.Tasks;
namespace PSManagement.Application.Customers.UseCases.Commands.CreateCustomer namespace PSManagement.Application.Customers.UseCases.Commands.CreateCustomer
{ {
class CreateCustomerCommandValidator public class CreateCustomerCommandValidator : AbstractValidator<CreateCustomerCommand>
{ {
public CreateCustomerCommandValidator()
{
RuleFor(x => x.CustomerName).NotEmpty();
RuleFor(x => x.Email).EmailAddress();
}
} }
} }
using FluentResults;
using PSManagement.Application.Customers.Common;
using PSManagement.SharedKernel.CQRS.Query;
using System;
using System.Linq;
using System.Text;
namespace PSManagement.Application.Customers.UseCases.Queries.GetCustomer
{
public record GetCustomerQuery(int customerId) : IQuery<Result<CustomerDTO>>;
}
using AutoMapper;
using FluentResults;
using PSManagement.Application.Customers.Common;
using PSManagement.Domain.Customers.Aggregate;
using PSManagement.Domain.Customers.DomainErrors;
using PSManagement.Domain.Customers.Repositories;
using PSManagement.SharedKernel.CQRS.Query;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PSManagement.Application.Customers.UseCases.Queries.GetCustomer
{
public class GetCustomerQueryHandler : IQueryHandler<GetCustomerQuery, Result<CustomerDTO>>
{
private readonly ICustomersRepository _customersRepository;
private readonly IMapper _mapper;
public GetCustomerQueryHandler(ICustomersRepository customersRepository, IMapper mapper)
{
_customersRepository = customersRepository;
_mapper = mapper;
}
public async Task<Result<CustomerDTO>> Handle(GetCustomerQuery request, CancellationToken cancellationToken)
{
Customer customer = await _customersRepository.GetByIdAsync(request.customerId);
if (customer is null) {
return Result.Fail(CustomerErrors.InvalidEntryError);
}
return Result.Ok(_mapper.Map<CustomerDTO>(customer));
}
}
}
using FluentResults;
using PSManagement.Application.Customers.Common;
using PSManagement.SharedKernel.CQRS.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Application.Customers.UseCases.Queries.ListAllCustomers
{
public record ListAllCustomersQuery() : IQuery<Result<IEnumerable<CustomerDTO>>>;
}
using AutoMapper;
using FluentResults;
using PSManagement.Application.Customers.Common;
using PSManagement.Domain.Customers.Repositories;
using PSManagement.SharedKernel.CQRS.Query;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PSManagement.Application.Customers.UseCases.Queries.ListAllCustomers
{
public class ListAllCustomersQueryHandler : IQueryHandler<ListAllCustomersQuery, Result<IEnumerable<CustomerDTO>>>
{
private readonly ICustomersRepository _customersRepository;
private readonly IMapper _mapper;
public ListAllCustomersQueryHandler(ICustomersRepository customersRepository, IMapper mapper)
{
_customersRepository = customersRepository;
_mapper = mapper;
}
public async Task<Result<IEnumerable<CustomerDTO>>> Handle(ListAllCustomersQuery request, CancellationToken cancellationToken)
{
return Result.Ok( _mapper.Map<IEnumerable<CustomerDTO>>(await _customersRepository.ListAsync()));
}
}
}
...@@ -5,6 +5,8 @@ using MediatR; ...@@ -5,6 +5,8 @@ using MediatR;
using System.Reflection; using System.Reflection;
using AutoMapper; using AutoMapper;
using PSManagement.Application.Mappers; using PSManagement.Application.Mappers;
using FluentValidation;
using PSManagement.Application.Behaviors.ValidationBehavior;
namespace PSManagement.Application.DI namespace PSManagement.Application.DI
{ {
...@@ -13,7 +15,16 @@ namespace PSManagement.Application.DI ...@@ -13,7 +15,16 @@ namespace PSManagement.Application.DI
public static IServiceCollection AddApplication(this IServiceCollection services) public static IServiceCollection AddApplication(this IServiceCollection services)
{ {
//services.AddMediatR(); //services.AddMediatR();
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddMediatR(typeof(DependencyInjection).Assembly);
// Register the pipeline behaviors explicitly
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
// Register FluentValidation validators
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
services.AddAutoMapper(typeof(CustomerMapperConfiguration)); services.AddAutoMapper(typeof(CustomerMapperConfiguration));
......
...@@ -5,17 +5,16 @@ ...@@ -5,17 +5,16 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Abstraction\" />
<Folder Include="Behaviors\AuthorizationBehavior\" /> <Folder Include="Behaviors\AuthorizationBehavior\" />
<Folder Include="Customers\UseCases\Queries\ListAllCustomers\" />
<Folder Include="Customers\UseCases\Queries\GetCustomer\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="7.0.1" /> <PackageReference Include="AutoMapper" Version="7.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="5.0.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="5.0.1" />
<PackageReference Include="MediatR" Version="5.1.0" /> <PackageReference Include="FluentValidation" Version="8.6.3" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="5.1.0" /> <PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="8.6.3" />
<PackageReference Include="MediatR" Version="8.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
</ItemGroup> </ItemGroup>
......
...@@ -14,7 +14,7 @@ namespace PSManagement.Domain.Customers.Aggregate ...@@ -14,7 +14,7 @@ namespace PSManagement.Domain.Customers.Aggregate
public String CustomerName { get; set; } public String CustomerName { get; set; }
public Address Address { get; set; } public Address Address { get; set; }
public String Email { get; set; } public String Email { get; set; }
public IEnumerable<ContactInfo> ContactInfo { get; private set; } public ICollection<ContactInfo> ContactInfo { get; private set; }
public Customer() public Customer()
{ {
...@@ -34,8 +34,7 @@ namespace PSManagement.Domain.Customers.Aggregate ...@@ -34,8 +34,7 @@ namespace PSManagement.Domain.Customers.Aggregate
{ {
ContactInfo = new List<ContactInfo>(); ContactInfo = new List<ContactInfo>();
} }
ContactInfo= ContactInfo.Append(contactInfo); ContactInfo.Add(contactInfo);
} }
......
using FluentResults; using PSManagement.SharedKernel.DomainErrors;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
...@@ -9,6 +9,6 @@ namespace PSManagement.Domain.Customers.DomainErrors ...@@ -9,6 +9,6 @@ namespace PSManagement.Domain.Customers.DomainErrors
{ {
public static class CustomerErrors public static class CustomerErrors
{ {
public static Error InvalidEntryError { get; } = new Error("Customer Invalid Entry Erorr."); public static DomainError InvalidEntryError { get; } = new DomainError("Invalid Customer Entry.",new DomainError("Invalid Customer Data"));
} }
} }
...@@ -13,17 +13,17 @@ namespace PSManagement.Domain.Customers.Entities ...@@ -13,17 +13,17 @@ namespace PSManagement.Domain.Customers.Entities
public sealed class ContactInfo : BaseEntity public sealed class ContactInfo : BaseEntity
{ {
public String ContactType { get; private set; } public String ContactType { get; private set; }
public String ConatctValue { get; private set; } public String ContactValue { get; private set; }
public ContactInfo(string conatctValue, string contactType) public ContactInfo(string contactValue, string contactType)
{ {
ConatctValue = conatctValue; ContactValue = contactValue;
ContactType = contactType; ContactType = contactType;
} }
public ContactInfo() public ContactInfo()
{ {
} }
} }
......
using PSManagement.Domain.Employees.Aggregate;
using PSManagement.SharedKernel.Aggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.Departments.Aggregate
{
public class Department :IAggregateRoot
{
public String Name { get; set; }
public Department(string name)
{
Name = name;
}
public Department()
{
}
}
}
using PSManagement.SharedKernel.Aggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.Employees.Aggregate
{
public class Employee :IAggregateRoot
{
public int HIASTId{ get; set; }
public PersonalInfo PersonalInfo { get; set; }
public Availability Availability { get; set; }
public Employee()
{
}
public Employee(Availability availability, PersonalInfo personalInfo, int hiastId)
{
Availability = availability;
PersonalInfo = personalInfo;
HIASTId = hiastId;
}
}
public record PersonalInfo(
String FirstName ,
String LastName
);
public record Availability (
int WorkingHours ,
Boolean IsAvailable
);
}
using FluentResults;
using PSManagement.SharedKernel.DomainErrors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.Identity.DomainErrors
{
public class InvalidLoginDataError : IDomainError
{
public List<IError> Reasons => new(new[] { new Error("The User Email Or Password Wrong.") });
public string Message => "Invalid Login Attempt.";
public Dictionary<string, object> Metadata => new();
}
}
using FluentResults; using PSManagement.SharedKernel.DomainErrors;
using PSManagement.SharedKernel.DomainErrors;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
...@@ -8,12 +7,10 @@ using System.Threading.Tasks; ...@@ -8,12 +7,10 @@ using System.Threading.Tasks;
namespace PSManagement.Domain.Identity.DomainErrors namespace PSManagement.Domain.Identity.DomainErrors
{ {
public class AlreadyExistError : IDomainError public class UserErrors
{ {
public List<IError> Reasons => new(new[] { new Error("The User Email Already Exist.") }); public static readonly DomainError AlreadyUserExist = new ("The User Email Already Exist.", new DomainError("User email is already exist"));
public static readonly DomainError InvalidLoginAttempt = new ("The User Email or Password Are Incorrect.",new DomainError( "invalid credentails for login"));
public string Message => "The Email Is Already Exist.";
public Dictionary<string, object> Metadata => new();
} }
} }
...@@ -7,14 +7,8 @@ ...@@ -7,14 +7,8 @@
<ItemGroup> <ItemGroup>
<Folder Include="Identity\Entities\" /> <Folder Include="Identity\Entities\" />
<Folder Include="Identity\ValueObjects\" /> <Folder Include="Identity\ValueObjects\" />
<Folder Include="Employees\" />
<Folder Include="Departments\" />
<Folder Include="Phases\" />
<Folder Include="ProjectTypes\" />
<Folder Include="Tracking\" />
<Folder Include="Projects\DomainErrors\" /> <Folder Include="Projects\DomainErrors\" />
<Folder Include="Projects\Entities\" /> <Folder Include="Projects\Entities\" />
<Folder Include="Projects\ValueObjects\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
using PSManagement.SharedKernel.Aggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.ProjectTypes.Aggregate
{
public class ProjectType : IAggregateRoot
{
public String TypeName { get; set; }
public String Description { get; set; }
public int WorkerCount { get; set; }
}
}
using System; using PSManagement.Domain.Departments.Aggregate;
using PSManagement.Domain.Employees.Aggregate;
using PSManagement.Domain.Steps.Aggregate;
using PSManagement.SharedKernel.Aggregate;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
...@@ -6,7 +9,21 @@ using System.Threading.Tasks; ...@@ -6,7 +9,21 @@ using System.Threading.Tasks;
namespace PSManagement.Domain.Projects.Aggregate namespace PSManagement.Domain.Projects.Aggregate
{ {
class Project public class Project : IAggregateRoot
{ {
public ProposalInfo ProposalInfo { get; set; }
public ProjectInfo ProjectInfo { get; set; }
public Aggreement ProjectAggreement { get; set; }
public ICollection<Employee> Participants { get; set; }
public ICollection<Step> Steps { get; set; }
public Employee TeamLeader { get; set; }
public Department Executer { get; set; }
public Employee Proposer { get; set; }
public Project()
{
}
} }
} }
using System;
namespace PSManagement.Domain.Projects.Aggregate
{
public record Aggreement (
int AggreementNumber ,
DateTime AggreementDate
);
}
using System;
namespace PSManagement.Domain.Projects.Aggregate
{
public record ProjectInfo(
String Name ,
String Code ,
String Description
);
}
using PSManagement.Domain.Customers.Aggregate;
using System;
namespace PSManagement.Domain.Projects.Aggregate
{
public record ProposalInfo (
int ProposingBookNumber ,
DateTime ProposingBookDate
);
}
using PSManagement.Domain.Steps.Entities;
using PSManagement.SharedKernel.Aggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.Steps.Aggregate
{
public class Step :IAggregateRoot
{
public String StepName { get; set; }
public String Description { get; set; }
public int Duration { get; set; }
public DateTime StartDate { get; set; }
public ICollection<Item> Purchases { get; set; }
public Step()
{
}
}
}
using PSManagement.SharedKernel.Entities;
using PSManagement.SharedKernel.ValueObjects;
using System;
namespace PSManagement.Domain.Steps.Entities
{
public class Item : BaseEntity
{
public string ItemName { get; set; }
public string ItemDescription { get; set; }
public Money Price { get; set; }
public Item()
{
}
}
}
using PSManagement.Domain.Projects.Aggregate;
using PSManagement.Domain.Tracking.Entities;
using PSManagement.SharedKernel.Aggregate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSManagement.Domain.Tracking
{
public class Track : IAggregateRoot
{
public DateTime TrackDate { get; set; }
public String TrackNote { get; set; }
public Project Project { get; set; }
public ICollection<StepTrack> StepsTracks { get; set; }
public Track()
{
}
}
}
using PSManagement.Domain.Employees.Aggregate;
using PSManagement.SharedKernel.Entities;
namespace PSManagement.Domain.Tracking.Entities
{
public class EmployeeTrack : BaseEntity
{
public Employee Employee { get; set; }
public int WorkingHour { get; set; }
public EmployeeTrack()
{
}
}
}
using PSManagement.Domain.Steps.Aggregate;
using PSManagement.SharedKernel.Entities;
using System.Collections.Generic;
namespace PSManagement.Domain.Tracking.Entities
{
public class StepTrack : BaseEntity
{
public Step Step { get; set; }
public IEnumerable<EmployeeTrack> EmployeeTracks { get; set; }
public StepTrack()
{
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment