Add new API to only fetch project information to load in dropdowns. Full project details including progress will be fatched latter when required
This commit is contained in:
parent
d5e7d38101
commit
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,23 +754,24 @@ 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<Project> projectlist = await _context.Projects
|
List<Project> projectlist = await _context.Projects
|
||||||
.Where(p => projectList.Contains(p.Id))
|
.Where(p => projectList.Contains(p.Id))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(projects, "Success.", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(projects, "Success.", 200));
|
||||||
}
|
}
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
@ -797,7 +852,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid details.", "All Field is required", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid details.", "All Field is required", 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