Browse Source

ForgetPasswordDto change

zinab_elgendy 11 months ago
parent
commit
1e13323801

+ 2 - 1
MTWorkHR.API/Controllers/AuthController.cs

@@ -52,7 +52,8 @@ namespace MTWorkHR.API.Controllers
         {
             return await _userService.ForgetPassword(model);
         }
-        [HttpGet]
+
+        [HttpGet("confirmEmail")]
         [ProducesResponseType(StatusCodes.Status200OK)]
 
         public async Task<bool> ConfirmEmail(ForgetPasswordDto model)

+ 4 - 6
MTWorkHR.Application/Dtos/Identity/ForgetPasswordDto.cs

@@ -4,13 +4,11 @@ namespace MTWorkHR.Application.Models
 {
     public class ForgetPasswordDto
     {
-        [Required]
-        public string UserId { get; set; }
-        [Required]
-        public string Token { get; set; }
+        public string? UserId { get; set; }
+        public string? Token { get; set; }
         
-        public string Password { get; set; }
-        public string Email { get; set; }
+        public string? Password { get; set; }
+        public string? Email { get; set; }
 
     }
 }

+ 1 - 0
MTWorkHR.Application/Dtos/User/UserTaskDto.cs

@@ -20,6 +20,7 @@ namespace MTWorkHR.Application.Models
 
         public long StatusId { get; set; }
         public List<AttachmentDto> TaskAttachments { get; set; }
+        public List<UserTaskHistoryDto> UserTaskHistories { get; set; }
 
     }
 }

+ 23 - 0
MTWorkHR.Application/Dtos/User/UserTaskHistoryDto.cs

@@ -0,0 +1,23 @@
+using Microsoft.AspNetCore.Http;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.Entities.Base;
+using MTWorkHR.Core.Global;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MTWorkHR.Application.Models
+{
+    public class UserTaskHistoryDto : EntityDto
+    {
+        public long AssignedToUserId { get; set; }
+        [MaxLength(500)]
+        public string? Comment { get; set; }
+
+        public long TaskId { get; set; }
+
+        public long CurrentStatusId { get; set; }
+
+        public bool IsDeleted { get; set; }
+
+    }
+}

+ 2 - 1
MTWorkHR.Application/Mapper/MappingProfile.cs

@@ -61,8 +61,9 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<ProjectDto, Project>().ReverseMap();
             CreateMap<UserTaskDto, UserTask>().ReverseMap();
             CreateMap<UserTaskAttachment, AttachmentDto>().ReverseMap();
+            CreateMap<UserTaskHistory, UserTaskHistoryDto>().ReverseMap();
 
-
+            
 
         }
     }

+ 24 - 8
MTWorkHR.Application/Services/User/UserTaskService.cs

@@ -9,6 +9,7 @@ using MTWorkHR.Core.Global;
 using MTWorkHR.Identity.Entities;
 using MTWorkHR.Infrastructure.Repositories;
 using MTWorkHR.Infrastructure.UnitOfWorks;
+using MTWorkHR.Core.IRepositories.Base;
 
 namespace MTWorkHR.Application.Services
 {
@@ -26,12 +27,12 @@ namespace MTWorkHR.Application.Services
         }
 
 
-        //public override async Task<ProjectDto> GetById(long id)
-        //{
-        //    var entity = await _unitOfWork.Project.GetByIdAsync(id);
-        //    var response = MapperObject.Mapper.Map<ProjectDto>(entity);
-        //    return response;
-        //}
+        public override async Task<UserTaskDto> GetById(long id)
+        {
+            var entity = await _unitOfWork.UserTask.GetByIdWithAllChildren(id);
+            var response = MapperObject.Mapper.Map<UserTaskDto>(entity);
+            return response;
+        }
 
         //public override async Task<List<ProjectDto>> GetAll()
         //{
@@ -46,7 +47,7 @@ namespace MTWorkHR.Application.Services
             if(input.TaskAttachments?.Count > 0)
                 if ( !await _fileService.CopyFileToActualFolder(input.TaskAttachments.ToList()))
                     throw new AppException(ExceptionEnum.CouldNotMoveFiles);
-            var entity = Mapper.MapperObject.Mapper.Map<UserTask>(input);
+            var entity = MapperObject.Mapper.Map<UserTask>(input);
             if (entity is null)
             {
                 throw new AppException(ExceptionEnum.MapperIssue);
@@ -55,8 +56,23 @@ namespace MTWorkHR.Application.Services
             var task = await _unitOfWork.UserTask.AddAsync(entity);
             await _unitOfWork.CompleteAsync();
 
-            var response = Mapper.MapperObject.Mapper.Map<UserTaskDto>(task);
+            var response = MapperObject.Mapper.Map<UserTaskDto>(task);
             return response;
         }
+
+
+        public override async Task<UserTaskDto> Update(UserTaskDto input)
+        {
+            var entitiy = await _unitOfWork.UserTask.GetByIdAsync(input.Id);
+
+            if (entitiy == null)
+                throw new AppException(ExceptionEnum.RecordNotExist);
+
+            MapperObject.Mapper.Map(input, entitiy, typeof(UserTaskDto), typeof(UserTask));
+
+            await _unitOfWork.CompleteAsync();
+
+            return input;
+        }
     }
 }

+ 2 - 0
MTWorkHR.Core/Entities/User/UserTask.cs

@@ -27,6 +27,8 @@ namespace MTWorkHR.Core.Entities
         [ForeignKey("StatusId")]
         public UserTaskStatus TaskStatus { get; set; }
         public List<UserTaskAttachment> TaskAttachments { get; set; }
+        public List<UserTaskHistory> UserTaskHistories { get; set; }
+
 
     }
 }

+ 2 - 0
MTWorkHR.Core/IRepositories/IUserTaskRepository.cs

@@ -11,5 +11,7 @@ namespace MTWorkHR.Core.IRepositories
 {
     public interface IUserTaskRepository : IRepository<UserTask>
     {
+        Task<UserTask> GetByIdWithAllChildren(long id);
+
     }
 }

+ 8 - 8
MTWorkHR.Identity/DBContext/HRIdentityDBContext.cs

@@ -1,6 +1,7 @@
 using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore;
 using MTWorkHR.Core.Entities.Base;
+using MTWorkHR.Core.Global;
 using MTWorkHR.Identity.Entities;
 
 
@@ -8,10 +9,10 @@ namespace MTWorkHR.Identity.DBContext
 {
     public class HRIdentityDBContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
     {
-       // private readonly GlobalInfo _globalInfo;
+        private readonly GlobalInfo _globalInfo;
 
-        public HRIdentityDBContext(DbContextOptions<HRIdentityDBContext> options/*, GlobalInfo globalInfo*/) : base(options) {
-           // this._globalInfo = globalInfo;
+        public HRIdentityDBContext(DbContextOptions<HRIdentityDBContext> options, GlobalInfo globalInfo) : base(options) {
+            this._globalInfo = globalInfo;
 
         }
         public DbSet<AttachmentType> AttachmentTypes { get; set; }
@@ -57,10 +58,9 @@ namespace MTWorkHR.Identity.DBContext
             {
                 if (change.State == EntityState.Added)
                 {
-                    //if (change.Entity.GetType() == typeof(IAuditEntityx<>))
                     if (change.Entity is IAudit)
                     {
-                      //  ((IAudit)change.Entity).CreateUser = _globalInfo.UserId;
+                        ((IAudit)change.Entity).CreateUser = _globalInfo.UserId;
                         ((IAudit)change.Entity).CreateDate = DateTime.Now;
                     }
                 }
@@ -70,13 +70,13 @@ namespace MTWorkHR.Identity.DBContext
                     if (change.Entity is IAudit
                         && ((change.Entity is IFullAudit && !((IFullAudit)change.Entity).IsDeleted) || change.Entity is not IFullAudit))
                     {
-                      //  ((IAudit)change.Entity).UpdateUser = _globalInfo.UserId;
+                        ((IAudit)change.Entity).UpdateUser = _globalInfo.UserId;
                         ((IAudit)change.Entity).UpdateDate = DateTime.Now;
                     }
 
                     if (change.Entity is IFullAudit && ((IFullAudit)change.Entity).IsDeleted)
                     {
-                     //   ((IFullAudit)change.Entity).DeleteUserId = _globalInfo.UserId;
+                        ((IFullAudit)change.Entity).DeleteUserId = _globalInfo.UserId;
                     }
 
                 }
@@ -86,6 +86,6 @@ namespace MTWorkHR.Identity.DBContext
                 }
             }
         }
-        #endregion 
+        #endregion       
     }
 }

+ 88 - 0
MTWorkHR.Infrastructure/Data/Extensions/BuilderHasIndexExtensions.cs

@@ -0,0 +1,88 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Query;
+using System.Collections.ObjectModel;
+
+namespace MTWorkHR.Infrastructure.Data
+{
+    public static class BuilderHasIndexExtensions
+    {
+
+        static readonly MethodInfo HasIndexMethod = typeof(BuilderHasIndexExtensions)
+                .GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
+                .Single(t => t.IsGenericMethod && t.Name == nameof(SetIndex));
+
+        public static void HasIndexOnAllEntities<TEntityInterface>(
+            this ModelBuilder builder,
+            Expression<Func<TEntityInterface, object>> filterExpression)
+        {
+            foreach (var type in builder.Model.GetEntityTypes()
+                .Where(t => t.BaseType == null)
+                .Select(t => t.ClrType)
+                .Where(t => typeof(TEntityInterface).IsAssignableFrom(t)))
+            {
+                builder.SetEntityIndex(
+                    type,
+                    filterExpression);
+            }
+        }
+
+        static void SetEntityIndex<TEntityInterface>(
+            this ModelBuilder builder,
+            Type entityType,
+            Expression<Func<TEntityInterface, object>> filterExpression)
+        {
+            HasIndexMethod
+                .MakeGenericMethod(entityType, typeof(TEntityInterface))
+               .Invoke(null, new object[] { builder, filterExpression });
+        }
+
+        static void SetIndex<TEntity, TEntityInterface>(
+            this ModelBuilder builder,
+            Expression<Func<TEntityInterface, object>> filterExpression)
+                where TEntityInterface : class
+                where TEntity : class, TEntityInterface
+        {
+            var concreteExpression = filterExpression
+                .Convert<TEntityInterface, TEntity>();
+            builder.Entity<TEntity>()
+                .HasIndex(concreteExpression);
+        }
+
+    }
+
+    public static class HasIndexExpressionExtensions
+    {
+        // This magic is courtesy of this StackOverflow post.
+        // https://stackoverflow.com/questions/38316519/replace-parameter-type-in-lambda-expression
+        // I made some tweaks to adapt it to our needs - @haacked
+        public static Expression<Func<TTarget, object>> Convert<TSource, TTarget>(
+            this Expression<Func<TSource, object>> root)
+        {
+            var visitor = new ParameterTypeVisitor<TSource, TTarget>();
+            return (Expression<Func<TTarget, object>>)visitor.Visit(root);
+        }
+        class ParameterTypeVisitor<TSource, TTarget> : ExpressionVisitor
+        {
+            private ReadOnlyCollection<ParameterExpression> _parameters;
+
+            protected override Expression VisitParameter(ParameterExpression node)
+            {
+                return _parameters?.FirstOrDefault(p => p.Name == node.Name)
+                       ?? (node.Type == typeof(TSource) ? Expression.Parameter(typeof(TTarget), node.Name) : node);
+            }
+
+            protected override Expression VisitLambda<T>(Expression<T> node)
+            {
+                _parameters = VisitAndConvert(node.Parameters, "VisitLambda");
+                return Expression.Lambda(Visit(node.Body), _parameters);
+            }
+        }
+    }
+
+}

+ 108 - 0
MTWorkHR.Infrastructure/Data/Extensions/BuilderSetQueryFilterExtensions.cs

@@ -0,0 +1,108 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Query;
+using System.Collections.ObjectModel;
+
+namespace MTWorkHR.Infrastructure.Data
+{
+    public static class BuilderSetQueryFilterExtensions
+    {
+
+        static readonly MethodInfo SetQueryFilterMethod = typeof(BuilderSetQueryFilterExtensions)
+                .GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
+                .Single(t => t.IsGenericMethod && t.Name == nameof(SetQueryFilter));
+
+        public static void SetQueryFilterOnAllEntities<TEntityInterface>(
+            this ModelBuilder builder,
+            Expression<Func<TEntityInterface, bool>> filterExpression)
+        {
+            foreach (var type in builder.Model.GetEntityTypes()
+                .Where(t => t.BaseType == null)
+                .Select(t => t.ClrType)
+                .Where(t => typeof(TEntityInterface).IsAssignableFrom(t)))
+            {
+                builder.SetEntityQueryFilter(
+                    type,
+                    filterExpression);
+            }
+        }
+
+        static void SetEntityQueryFilter<TEntityInterface>(
+            this ModelBuilder builder,
+            Type entityType,
+            Expression<Func<TEntityInterface, bool>> filterExpression)
+        {
+            SetQueryFilterMethod
+                .MakeGenericMethod(entityType, typeof(TEntityInterface))
+               .Invoke(null, new object[] { builder, filterExpression });
+        }
+
+        static void SetQueryFilter<TEntity, TEntityInterface>(
+            this ModelBuilder builder,
+            Expression<Func<TEntityInterface, bool>> filterExpression)
+                where TEntityInterface : class
+                where TEntity : class, TEntityInterface
+        {
+            var concreteExpression = filterExpression
+                .Convert<TEntityInterface, TEntity>();
+            builder.Entity<TEntity>()
+                .AppendQueryFilter(concreteExpression);
+        }
+
+        // CREDIT: This comment by magiak on GitHub https://github.com/dotnet/efcore/issues/10275#issuecomment-785916356
+        static void AppendQueryFilter<T>(this EntityTypeBuilder entityTypeBuilder, Expression<Func<T, bool>> expression)
+            where T : class
+        {
+            var parameterType = Expression.Parameter(entityTypeBuilder.Metadata.ClrType);
+
+            var expressionFilter = ReplacingExpressionVisitor.Replace(
+                expression.Parameters.Single(), parameterType, expression.Body);
+
+            if (entityTypeBuilder.Metadata.GetQueryFilter() != null)
+            {
+                var currentQueryFilter = entityTypeBuilder.Metadata.GetQueryFilter();
+                var currentExpressionFilter = ReplacingExpressionVisitor.Replace(
+                    currentQueryFilter.Parameters.Single(), parameterType, currentQueryFilter.Body);
+                expressionFilter = Expression.AndAlso(currentExpressionFilter, expressionFilter);
+            }
+
+            var lambdaExpression = Expression.Lambda(expressionFilter, parameterType);
+            entityTypeBuilder.HasQueryFilter(lambdaExpression);
+        }
+    }
+
+    public static class QueryFilterExpressionExtensions
+    {
+        // This magic is courtesy of this StackOverflow post.
+        // https://stackoverflow.com/questions/38316519/replace-parameter-type-in-lambda-expression
+        // I made some tweaks to adapt it to our needs - @haacked
+        public static Expression<Func<TTarget, bool>> Convert<TSource, TTarget>(
+            this Expression<Func<TSource, bool>> root)
+        {
+            var visitor = new ParameterTypeVisitor<TSource, TTarget>();
+            return (Expression<Func<TTarget, bool>>)visitor.Visit(root);
+        }
+
+        class ParameterTypeVisitor<TSource, TTarget> : ExpressionVisitor
+        {
+            private ReadOnlyCollection<ParameterExpression> _parameters;
+
+            protected override Expression VisitParameter(ParameterExpression node)
+            {
+                return _parameters?.FirstOrDefault(p => p.Name == node.Name)
+                       ?? (node.Type == typeof(TSource) ? Expression.Parameter(typeof(TTarget), node.Name) : node);
+            }
+
+            protected override Expression VisitLambda<T>(Expression<T> node)
+            {
+                _parameters = VisitAndConvert(node.Parameters, "VisitLambda");
+                return Expression.Lambda(Visit(node.Body), _parameters);
+            }
+        }
+    }
+}

+ 6 - 2
MTWorkHR.Infrastructure/Data/HRDataContext.cs

@@ -30,8 +30,9 @@ namespace MTWorkHR.Infrastructure.Data
 
         protected override void OnModelCreating(ModelBuilder modelBuilder)
         {
-            modelBuilder.ApplyConfigurationsFromAssembly(typeof(HRDataContext).Assembly);
             base.OnModelCreating(modelBuilder);
+            SetGlobalFilters(modelBuilder);
+            modelBuilder.ApplyConfigurationsFromAssembly(typeof(HRDataContext).Assembly);
         }
         public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
         {
@@ -45,6 +46,9 @@ namespace MTWorkHR.Infrastructure.Data
             }
             return base.SaveChangesAsync(cancellationToken);
         }
-       
+        private void SetGlobalFilters(ModelBuilder builder)
+        {
+            builder.SetQueryFilterOnAllEntities<ISoftDelete>(p => !p.IsDeleted);
+        }
     }
 }

+ 693 - 0
MTWorkHR.Infrastructure/Migrations/20240226083813_userHistory.Designer.cs

@@ -0,0 +1,693 @@
+// <auto-generated />
+using System;
+using MTWorkHR.Infrastructure.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    [DbContext(typeof(HRDataContext))]
+    [Migration("20240226083813_userHistory")]
+    partial class userHistory
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "8.0.1")
+                .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+            SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.AuthLog", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Channel")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("CreateUser")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorCode")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorDescription")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("InnerException")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Input")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Method")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("QueryString")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServerIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServiceResponseTimeInSeconds")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("userAgent")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("AuthLogs");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.Base.AttachmentType", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<bool>("IsRequired")
+                        .HasColumnType("bit");
+
+                    b.Property<string>("NameAr")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("NameEn")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("AttachmentType");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1L,
+                            IsRequired = false,
+                            NameAr = "السيرة الذاتية",
+                            NameEn = "CV"
+                        },
+                        new
+                        {
+                            Id = 2L,
+                            IsRequired = false,
+                            NameAr = "الهوية",
+                            NameEn = "Identification"
+                        });
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.Company", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("CRNumber")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("CompanyName")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(3);
+
+                    b.Property<string>("CreateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(1);
+
+                    b.Property<bool>("IsDeleted")
+                        .HasColumnType("bit");
+
+                    b.Property<int>("TaxNumber")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("UpdateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(4);
+
+                    b.Property<string>("UpdateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(2);
+
+                    b.Property<long>("UserId")
+                        .HasColumnType("bigint");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Companies");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.FileLog", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Channel")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("CreateUser")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorCode")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorDescription")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("InnerException")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Input")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Method")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("QueryString")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServerIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServiceResponseTimeInSeconds")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("userAgent")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("FileLogs");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.Project", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("NameAr")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("NameEn")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Projects");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.RoleLog", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Channel")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("CreateUser")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorCode")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorDescription")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("InnerException")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Input")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Method")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("QueryString")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServerIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServiceResponseTimeInSeconds")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("userAgent")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("RoleLogs");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.SettingLog", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Channel")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("CreateUser")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorCode")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorDescription")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("InnerException")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Input")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Method")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("QueryString")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServerIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServiceResponseTimeInSeconds")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("userAgent")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("SettingLogs");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserLog", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Channel")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("CreateUser")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorCode")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ErrorDescription")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("InnerException")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Input")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("Method")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("QueryString")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServerIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("ServiceResponseTimeInSeconds")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserIP")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("userAgent")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("UserLogs");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTask", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<long>("AssignedUserId")
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(3);
+
+                    b.Property<string>("CreateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(1);
+
+                    b.Property<string>("DeleteUserId")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(8);
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("DueDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<bool>("IsDeleted")
+                        .HasColumnType("bit")
+                        .HasColumnOrder(7);
+
+                    b.Property<int>("Priority")
+                        .HasColumnType("int");
+
+                    b.Property<long>("ProjectId")
+                        .HasColumnType("bigint");
+
+                    b.Property<long>("StatusId")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime?>("UpdateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(4);
+
+                    b.Property<string>("UpdateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(2);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProjectId");
+
+                    b.HasIndex("StatusId");
+
+                    b.ToTable("UserTasks");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTaskAttachment", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<long>("AttachmentTypeId")
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(3);
+
+                    b.Property<string>("CreateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(1);
+
+                    b.Property<string>("FileName")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("OriginalName")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<long>("TaskId")
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime?>("UpdateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(4);
+
+                    b.Property<string>("UpdateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(2);
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("AttachmentTypeId");
+
+                    b.HasIndex("TaskId");
+
+                    b.ToTable("UserTaskAttachments");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTaskHistory", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<long>("AssignedToUserId")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("Comment")
+                        .IsRequired()
+                        .HasMaxLength(500)
+                        .HasColumnType("nvarchar(500)");
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(3);
+
+                    b.Property<string>("CreateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(1);
+
+                    b.Property<long>("CurrentStatusId")
+                        .HasColumnType("bigint");
+
+                    b.Property<bool>("IsDeleted")
+                        .HasColumnType("bit");
+
+                    b.Property<DateTime?>("UpdateDate")
+                        .HasColumnType("datetime2")
+                        .HasColumnOrder(4);
+
+                    b.Property<string>("UpdateUser")
+                        .HasMaxLength(450)
+                        .HasColumnType("nvarchar(450)")
+                        .HasColumnOrder(2);
+
+                    b.Property<long?>("UserTaskId")
+                        .HasColumnType("bigint");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CurrentStatusId");
+
+                    b.HasIndex("UserTaskId");
+
+                    b.ToTable("UserTaskHistories");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTaskStatus", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("NameAr")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("NameEn")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("UserTaskStatuses");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTask", b =>
+                {
+                    b.HasOne("MTWorkHR.Core.Entities.Project", "Project")
+                        .WithMany()
+                        .HasForeignKey("ProjectId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("MTWorkHR.Core.Entities.UserTaskStatus", "TaskStatus")
+                        .WithMany()
+                        .HasForeignKey("StatusId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Project");
+
+                    b.Navigation("TaskStatus");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTaskAttachment", b =>
+                {
+                    b.HasOne("MTWorkHR.Core.Entities.Base.AttachmentType", "AttachmentType")
+                        .WithMany()
+                        .HasForeignKey("AttachmentTypeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("MTWorkHR.Core.Entities.UserTask", "UserTask")
+                        .WithMany("TaskAttachments")
+                        .HasForeignKey("TaskId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("AttachmentType");
+
+                    b.Navigation("UserTask");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTaskHistory", b =>
+                {
+                    b.HasOne("MTWorkHR.Core.Entities.UserTaskStatus", "TaskStatus")
+                        .WithMany()
+                        .HasForeignKey("CurrentStatusId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("MTWorkHR.Core.Entities.UserTask", null)
+                        .WithMany("UserTaskHistories")
+                        .HasForeignKey("UserTaskId");
+
+                    b.Navigation("TaskStatus");
+                });
+
+            modelBuilder.Entity("MTWorkHR.Core.Entities.UserTask", b =>
+                {
+                    b.Navigation("TaskAttachments");
+
+                    b.Navigation("UserTaskHistories");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 48 - 0
MTWorkHR.Infrastructure/Migrations/20240226083813_userHistory.cs

@@ -0,0 +1,48 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class userHistory : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<long>(
+                name: "UserTaskId",
+                table: "UserTaskHistories",
+                type: "bigint",
+                nullable: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_UserTaskHistories_UserTaskId",
+                table: "UserTaskHistories",
+                column: "UserTaskId");
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_UserTaskHistories_UserTasks_UserTaskId",
+                table: "UserTaskHistories",
+                column: "UserTaskId",
+                principalTable: "UserTasks",
+                principalColumn: "Id");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropForeignKey(
+                name: "FK_UserTaskHistories_UserTasks_UserTaskId",
+                table: "UserTaskHistories");
+
+            migrationBuilder.DropIndex(
+                name: "IX_UserTaskHistories_UserTaskId",
+                table: "UserTaskHistories");
+
+            migrationBuilder.DropColumn(
+                name: "UserTaskId",
+                table: "UserTaskHistories");
+        }
+    }
+}

+ 11 - 0
MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs

@@ -589,10 +589,15 @@ namespace MTWorkHR.Infrastructure.Migrations
                         .HasColumnType("nvarchar(450)")
                         .HasColumnOrder(2);
 
+                    b.Property<long?>("UserTaskId")
+                        .HasColumnType("bigint");
+
                     b.HasKey("Id");
 
                     b.HasIndex("CurrentStatusId");
 
+                    b.HasIndex("UserTaskId");
+
                     b.ToTable("UserTaskHistories");
                 });
 
@@ -666,12 +671,18 @@ namespace MTWorkHR.Infrastructure.Migrations
                         .OnDelete(DeleteBehavior.Cascade)
                         .IsRequired();
 
+                    b.HasOne("MTWorkHR.Core.Entities.UserTask", null)
+                        .WithMany("UserTaskHistories")
+                        .HasForeignKey("UserTaskId");
+
                     b.Navigation("TaskStatus");
                 });
 
             modelBuilder.Entity("MTWorkHR.Core.Entities.UserTask", b =>
                 {
                     b.Navigation("TaskAttachments");
+
+                    b.Navigation("UserTaskHistories");
                 });
 #pragma warning restore 612, 618
         }

+ 13 - 1
MTWorkHR.Infrastructure/Repositories/User/UserTaskRepository.cs

@@ -9,9 +9,21 @@ namespace MTWorkHR.Infrastructure.Repositories
 {
     public class UserTaskRepository : Repository<UserTask>, IUserTaskRepository
     {
+        private readonly DbSet<UserTask> dbSet;
+
         public UserTaskRepository(HRDataContext context) : base(context)
         {
-        }
+            dbSet = context.Set<UserTask>();
 
+        }
+        public async Task<UserTask> GetByIdWithAllChildren(long id)
+        {
+            return await dbSet
+                .Include(x => x.TaskAttachments).ThenInclude(a => a.AttachmentType)
+                .Include(x => x.UserTaskHistories)
+                .Include(x => x.TaskStatus)
+                .Include(x => x.Project)
+                .FirstOrDefaultAsync(x => x.Id == id);
+        }
     }
 }