Compare commits
	
		
			6 Commits
		
	
	
		
			4ccc690560
			...
			c689f2dfd8
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c689f2dfd8 | |||
| 5c019a2ff6 | |||
| cb185db4f3 | |||
| 1a51860517 | |||
| f275d08215 | |||
| d8ee5940fd | 
@ -91,5 +91,19 @@ namespace Marco.Pms.Model.Mapper
 | 
				
			|||||||
                EndDate = project.EndDate,
 | 
					                EndDate = project.EndDate,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        public static ProjectInfoVM ToProjectInfoVMFromProject(this Project project)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new ProjectInfoVM
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Id = project.Id,
 | 
				
			||||||
 | 
					                Name = project.Name,
 | 
				
			||||||
 | 
					                ShortName = project.ShortName,
 | 
				
			||||||
 | 
					                ProjectAddress = project.ProjectAddress,
 | 
				
			||||||
 | 
					                ProjectStatusId = project.ProjectStatusId,
 | 
				
			||||||
 | 
					                ContactPerson = project.ContactPerson,
 | 
				
			||||||
 | 
					                StartDate = project.StartDate,
 | 
				
			||||||
 | 
					                EndDate = project.EndDate,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,4 +15,17 @@
 | 
				
			|||||||
        public double CompletedWork { get; set; }
 | 
					        public double CompletedWork { get; set; }
 | 
				
			||||||
        public double PlannedWork { get; set; }
 | 
					        public double PlannedWork { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class ProjectInfoVM
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public Guid Id { get; set; }
 | 
				
			||||||
 | 
					        public string? Name { get; set; }
 | 
				
			||||||
 | 
					        public string? ShortName { get; set; }
 | 
				
			||||||
 | 
					        public string? ProjectAddress { get; set; }
 | 
				
			||||||
 | 
					        public string? ContactPerson { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public DateTime? StartDate { get; set; }
 | 
				
			||||||
 | 
					        public DateTime? EndDate { get; set; }
 | 
				
			||||||
 | 
					        public Guid ProjectStatusId { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,55 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
            _rolesHelper = rolesHelper;
 | 
					            _rolesHelper = rolesHelper;
 | 
				
			||||||
            _projectsHelper = projectHelper;
 | 
					            _projectsHelper = projectHelper;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [HttpGet("list/basic")]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> GetAllProjects()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!ModelState.IsValid)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var errors = ModelState.Values
 | 
				
			||||||
 | 
					                    .SelectMany(v => v.Errors)
 | 
				
			||||||
 | 
					                    .Select(e => e.ErrorMessage)
 | 
				
			||||||
 | 
					                    .ToList();
 | 
				
			||||||
 | 
					                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Guid tenantId = _userHelper.GetTenantId();
 | 
				
			||||||
 | 
					            var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Defensive check for null employee (important for robust APIs)
 | 
				
			||||||
 | 
					            if (LoggedInEmployee == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return Unauthorized(ApiResponse<object>.ErrorResponse("Employee not found.", null, 401));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					           
 | 
				
			||||||
 | 
					            List<Project> projects =  await _projectsHelper.GetMyProjects(tenantId, LoggedInEmployee);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 4. Project projection to ProjectInfoVM
 | 
				
			||||||
 | 
					            // This part is already quite efficient.
 | 
				
			||||||
 | 
					            // Ensure ToProjectInfoVMFromProject() is also optimized and doesn't perform N+1 queries.
 | 
				
			||||||
 | 
					            // If ProjectInfoVM only needs a subset of Project properties,
 | 
				
			||||||
 | 
					            // you can use a LINQ Select directly on the IQueryable before ToListAsync()
 | 
				
			||||||
 | 
					            // to fetch only the required columns from the database.
 | 
				
			||||||
 | 
					            List<ProjectInfoVM> response = projects
 | 
				
			||||||
 | 
					                .Select(project => project.ToProjectInfoVMFromProject())
 | 
				
			||||||
 | 
					                .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //List<ProjectInfoVM> response = new List<ProjectInfoVM>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //foreach (var project in projects)
 | 
				
			||||||
 | 
					            //{
 | 
				
			||||||
 | 
					            //    response.Add(project.ToProjectInfoVMFromProject());
 | 
				
			||||||
 | 
					            //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Ok(ApiResponse<object>.SuccessResponse(response, "Success.", 200));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpGet("list")]
 | 
					        [HttpGet("list")]
 | 
				
			||||||
        public async Task<IActionResult> GetAll()
 | 
					        public async Task<IActionResult> GetAll()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -51,21 +100,25 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            Guid tenantId = _userHelper.GetTenantId();
 | 
					            Guid tenantId = _userHelper.GetTenantId();
 | 
				
			||||||
            var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
 | 
					            var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
 | 
				
			||||||
            List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeID(LoggedInEmployee.Id);
 | 
					            //List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeID(LoggedInEmployee.Id);
 | 
				
			||||||
            string[] projectsId = [];
 | 
					            //string[] projectsId = [];
 | 
				
			||||||
            List<Project> projects = new List<Project>();
 | 
					            //List<Project> projects = new List<Project>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ///* User with permission manage project  can see all projects */
 | 
				
			||||||
 | 
					            //if (featurePermission != null && featurePermission.Exists(c => c.Id.ToString() == "172fc9b6-755b-4f62-ab26-55c34a330614"))
 | 
				
			||||||
 | 
					            //{
 | 
				
			||||||
 | 
					            //    projects = await _projectsHelper.GetAllProjectByTanentID(LoggedInEmployee.TenantId);
 | 
				
			||||||
 | 
					            //}
 | 
				
			||||||
 | 
					            //else
 | 
				
			||||||
 | 
					            //{
 | 
				
			||||||
 | 
					            //    List<ProjectAllocation> allocation = await _projectsHelper.GetProjectByEmployeeID(LoggedInEmployee.Id);
 | 
				
			||||||
 | 
					            //    projectsId = allocation.Select(c => c.ProjectId.ToString()).ToArray();
 | 
				
			||||||
 | 
					            //    projects = await _context.Projects.Where(c => projectsId.Contains(c.Id.ToString()) && c.TenantId == tenantId).ToListAsync();
 | 
				
			||||||
 | 
					            //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            List<Project> projects = await _projectsHelper.GetMyProjects(tenantId, LoggedInEmployee);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* User with permission manage project  can see all projects */
 | 
					 | 
				
			||||||
            if (featurePermission != null && featurePermission.Exists(c => c.Id.ToString() == "172fc9b6-755b-4f62-ab26-55c34a330614"))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                projects = await _projectsHelper.GetAllProjectByTanentID(LoggedInEmployee.TenantId);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                List<ProjectAllocation> allocation = await _projectsHelper.GetProjectByEmployeeID(LoggedInEmployee.Id);
 | 
					 | 
				
			||||||
                projectsId = allocation.Select(c => c.ProjectId.ToString()).ToArray();
 | 
					 | 
				
			||||||
                projects = await _context.Projects.Where(c => projectsId.Contains(c.Id.ToString()) && c.TenantId == tenantId).ToListAsync();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            List<ProjectListVM> response = new List<ProjectListVM>();
 | 
					            List<ProjectListVM> response = new List<ProjectListVM>();
 | 
				
			||||||
@ -701,7 +754,7 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (!projectList.Any())
 | 
					            if (!projectList.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return NotFound(ApiResponse<object>.SuccessResponse(new List<object>(), "No projects found.",200));
 | 
					                return NotFound(ApiResponse<object>.SuccessResponse(new List<object>(), "No projects found.", 200));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -712,7 +765,8 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
            List<ProjectListVM> projects = new List<ProjectListVM>();
 | 
					            List<ProjectListVM> projects = new List<ProjectListVM>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var project in projectlist) {
 | 
					            foreach (var project in projectlist)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                projects.Add(project.ToProjectListVMFromProject());
 | 
					                projects.Add(project.ToProjectListVMFromProject());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -728,19 +782,19 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
        [HttpPost("assign-projects/{employeeId}")]
 | 
					        [HttpPost("assign-projects/{employeeId}")]
 | 
				
			||||||
        public async Task<ActionResult> AssigneProjectsToEmployee([FromBody] List<ProjectsAllocationDto> projectAllocationDtos, [FromRoute] Guid employeeId)
 | 
					        public async Task<ActionResult> AssigneProjectsToEmployee([FromBody] List<ProjectsAllocationDto> projectAllocationDtos, [FromRoute] Guid employeeId)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if(projectAllocationDtos != null && employeeId != Guid.Empty)
 | 
					            if (projectAllocationDtos != null && employeeId != Guid.Empty)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Guid TenentID = GetTenantId();
 | 
					                Guid TenentID = GetTenantId();
 | 
				
			||||||
                List<object>? result = new List<object>();
 | 
					                List<object>? result = new List<object>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                foreach(var projectAllocationDto in projectAllocationDtos)
 | 
					                foreach (var projectAllocationDto in projectAllocationDtos)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    try
 | 
					                    try
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        ProjectAllocation projectAllocation = projectAllocationDto.ToProjectAllocationFromProjectsAllocationDto(TenentID,employeeId);
 | 
					                        ProjectAllocation projectAllocation = projectAllocationDto.ToProjectAllocationFromProjectsAllocationDto(TenentID, employeeId);
 | 
				
			||||||
                        ProjectAllocation? projectAllocationFromDb = await _context.ProjectAllocations.Where(c => c.EmployeeId == employeeId && c.ProjectId == projectAllocationDto.ProjectId && c.ReAllocationDate == null && c.TenantId == TenentID).SingleOrDefaultAsync();
 | 
					                        ProjectAllocation? projectAllocationFromDb = await _context.ProjectAllocations.Where(c => c.EmployeeId == employeeId && c.ProjectId == projectAllocationDto.ProjectId && c.ReAllocationDate == null && c.TenantId == TenentID).SingleOrDefaultAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if(projectAllocationFromDb != null)
 | 
					                        if (projectAllocationFromDb != null)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -785,7 +839,8 @@ namespace MarcoBMS.Services.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    catch (Exception ex) {
 | 
					                    catch (Exception ex)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        return Ok(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
 | 
					                        return Ok(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,25 @@
 | 
				
			|||||||
using Marco.Pms.DataAccess.Data;
 | 
					using Marco.Pms.DataAccess.Data;
 | 
				
			||||||
 | 
					using Marco.Pms.Model.Employees;
 | 
				
			||||||
 | 
					using Marco.Pms.Model.Entitlements;
 | 
				
			||||||
using Marco.Pms.Model.Projects;
 | 
					using Marco.Pms.Model.Projects;
 | 
				
			||||||
 | 
					using Marco.Pms.Model.Utilities;
 | 
				
			||||||
 | 
					using Marco.Pms.Model.ViewModels.Projects;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
using Microsoft.EntityFrameworkCore;
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using ModelServices.Helpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MarcoBMS.Services.Helpers
 | 
					namespace MarcoBMS.Services.Helpers
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class ProjectsHelper
 | 
					    public class ProjectsHelper
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly ApplicationDbContext _context;
 | 
					        private readonly ApplicationDbContext _context;
 | 
				
			||||||
 | 
					        private readonly RolesHelper _rolesHelper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ProjectsHelper(ApplicationDbContext context)
 | 
					
 | 
				
			||||||
 | 
					        public ProjectsHelper(ApplicationDbContext context, RolesHelper rolesHelper)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _context = context;
 | 
					            _context = context;
 | 
				
			||||||
 | 
					            _rolesHelper = rolesHelper;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<List<Project>> GetAllProjectByTanentID(Guid tanentID)
 | 
					        public async Task<List<Project>> GetAllProjectByTanentID(Guid tanentID)
 | 
				
			||||||
@ -42,7 +51,46 @@ namespace MarcoBMS.Services.Helpers
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<List<Project>> GetMyProjects(Guid tenantId, Employee LoggedInEmployee)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeID(LoggedInEmployee.Id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            string[] projectsId = [];
 | 
				
			||||||
 | 
					            List<Project> projects = new List<Project>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Define a common queryable base for projects
 | 
				
			||||||
 | 
					            IQueryable<Project> projectQuery = _context.Projects.Where(c => c.TenantId == tenantId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 2. Optimized Project Retrieval Logic
 | 
				
			||||||
 | 
					            // User with permission 'manage project' can see all projects
 | 
				
			||||||
 | 
					            if (featurePermission != null && featurePermission.Exists(c => c.Id.ToString() == "172fc9b6-755b-4f62-ab26-55c34a330614"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // If GetAllProjectByTanentID is already optimized and directly returns IQueryable or
 | 
				
			||||||
 | 
					                // directly executes with ToListAsync(), keep it.
 | 
				
			||||||
 | 
					                // If it does more complex logic or extra trips, consider inlining here.
 | 
				
			||||||
 | 
					                projects = await projectQuery.ToListAsync(); // Directly query the context
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // 3. Efficiently get project allocations and then filter projects
 | 
				
			||||||
 | 
					                // Load allocations only once
 | 
				
			||||||
 | 
					                var allocation = await GetProjectByEmployeeID(LoggedInEmployee.Id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // If there are no allocations, return an empty list early
 | 
				
			||||||
 | 
					                if (allocation == null || !allocation.Any())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return new List<Project>();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Use LINQ's Contains for efficient filtering by ProjectId
 | 
				
			||||||
 | 
					                var projectIds = allocation.Select(c => c.ProjectId).Distinct().ToList(); // Get distinct Guids
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Filter projects based on the retrieved ProjectIds
 | 
				
			||||||
 | 
					                projects = await projectQuery.Where(c => projectIds.Contains(c.Id)).ToListAsync();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return projects;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user