project details API is split into three APIs.
This commit is contained in:
parent
bc0ef0b88b
commit
3dd5e7f626
@ -1,10 +1,17 @@
|
||||
using Marco.Pms.Model.Dtos.Project;
|
||||
using Marco.Pms.Model.Master;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Projects
|
||||
{
|
||||
public class ProjectVM : ProjectDto
|
||||
public class ProjectVM
|
||||
{
|
||||
public List<BuildingVM>? Buildings { get; set; }
|
||||
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 StatusMaster? ProjectStatus { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Activities;
|
||||
using Marco.Pms.Model.Dtos.Project;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.Mapper;
|
||||
using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Employee;
|
||||
using Marco.Pms.Model.ViewModels.Projects;
|
||||
using Marco.Pms.Services.Hubs;
|
||||
using Marco.Pms.Services.Service;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@ -29,9 +28,16 @@ namespace MarcoBMS.Services.Controllers
|
||||
private readonly RolesHelper _rolesHelper;
|
||||
private readonly ProjectsHelper _projectsHelper;
|
||||
private readonly IHubContext<MarcoHub> _signalR;
|
||||
private readonly PermissionServices _permission;
|
||||
private readonly Guid ViewProjects;
|
||||
private readonly Guid ManageProject;
|
||||
private readonly Guid ViewInfra;
|
||||
private readonly Guid ManageInfra;
|
||||
private readonly Guid tenantId;
|
||||
|
||||
|
||||
public ProjectController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, RolesHelper rolesHelper, ProjectsHelper projectHelper, IHubContext<MarcoHub> signalR)
|
||||
public ProjectController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, RolesHelper rolesHelper, ProjectsHelper projectHelper,
|
||||
IHubContext<MarcoHub> signalR, PermissionServices permission)
|
||||
{
|
||||
_context = context;
|
||||
_userHelper = userHelper;
|
||||
@ -39,6 +45,12 @@ namespace MarcoBMS.Services.Controllers
|
||||
_rolesHelper = rolesHelper;
|
||||
_projectsHelper = projectHelper;
|
||||
_signalR = signalR;
|
||||
_permission = permission;
|
||||
ViewProjects = Guid.Parse("6ea44136-987e-44ba-9e5d-1cf8f5837ebc");
|
||||
ManageProject = Guid.Parse("172fc9b6-755b-4f62-ab26-55c34a330614");
|
||||
ViewInfra = Guid.Parse("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4");
|
||||
ManageInfra = Guid.Parse("f2aee20a-b754-4537-8166-f9507b44585b");
|
||||
tenantId = _userHelper.GetTenantId();
|
||||
|
||||
}
|
||||
|
||||
@ -177,133 +189,68 @@ namespace MarcoBMS.Services.Controllers
|
||||
[HttpGet("details/{id}")]
|
||||
public async Task<IActionResult> Details([FromRoute] Guid id)
|
||||
{
|
||||
// ProjectDetailsVM vm = new ProjectDetailsVM();
|
||||
|
||||
// Step 1: Validate model state
|
||||
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));
|
||||
|
||||
_logger.LogWarning("Invalid model state in Details endpoint. Errors: {@Errors}", errors);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||
}
|
||||
|
||||
var project = await _context.Projects.Where(c => c.TenantId == _userHelper.GetTenantId() && c.Id == id).Include(c => c.ProjectStatus).SingleOrDefaultAsync(); // includeProperties: "ProjectStatus,Tenant"); //_context.Stock.FindAsync(id);
|
||||
// Step 2: Get logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
_logger.LogInfo("Details requested by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}", loggedInEmployee.Id, id);
|
||||
|
||||
// Step 3: Check global view project permission
|
||||
var hasViewProjectPermission = await _permission.HasPermission(ViewProjects, loggedInEmployee.Id);
|
||||
if (!hasViewProjectPermission)
|
||||
{
|
||||
_logger.LogWarning("ViewProjects permission denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to view projects", 403));
|
||||
}
|
||||
|
||||
// Step 4: Check permission for this specific project
|
||||
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, id.ToString());
|
||||
if (!hasProjectPermission)
|
||||
{
|
||||
_logger.LogWarning("Project-specific access denied. EmployeeId: {EmployeeId}, ProjectId: {ProjectId}", loggedInEmployee.Id, id);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "You don't have access to this project", 403));
|
||||
}
|
||||
|
||||
// Step 5: Fetch project with status
|
||||
var project = await _context.Projects
|
||||
.Include(c => c.ProjectStatus)
|
||||
.FirstOrDefaultAsync(c => c.TenantId == tenantId && c.Id == id);
|
||||
|
||||
if (project == null)
|
||||
{
|
||||
_logger.LogWarning("Project not found. ProjectId: {ProjectId}", id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//var project = projects.Where(c => c.Id == id).SingleOrDefault();
|
||||
ProjectDetailsVM vm = await GetProjectViewModel(id, project);
|
||||
|
||||
ProjectVM projectVM = new ProjectVM();
|
||||
if (vm.project != null)
|
||||
{
|
||||
projectVM.Id = vm.project.Id;
|
||||
projectVM.Name = vm.project.Name;
|
||||
projectVM.ShortName = vm.project.ShortName;
|
||||
projectVM.ProjectAddress = vm.project.ProjectAddress;
|
||||
projectVM.ContactPerson = vm.project.ContactPerson;
|
||||
projectVM.StartDate = vm.project.StartDate;
|
||||
projectVM.EndDate = vm.project.EndDate;
|
||||
projectVM.ProjectStatusId = vm.project.ProjectStatusId;
|
||||
}
|
||||
projectVM.Buildings = new List<BuildingVM>();
|
||||
if (vm.buildings != null)
|
||||
{
|
||||
foreach (Building build in vm.buildings)
|
||||
{
|
||||
BuildingVM buildVM = new BuildingVM() { Id = build.Id, Description = build.Description, Name = build.Name };
|
||||
buildVM.Floors = new List<FloorsVM>();
|
||||
if (vm.floors != null)
|
||||
{
|
||||
foreach (Floor floorDto in vm.floors.Where(c => c.BuildingId == build.Id).ToList())
|
||||
{
|
||||
FloorsVM floorVM = new FloorsVM() { FloorName = floorDto.FloorName, Id = floorDto.Id };
|
||||
floorVM.WorkAreas = new List<WorkAreaVM>();
|
||||
|
||||
if (vm.workAreas != null)
|
||||
{
|
||||
foreach (WorkArea workAreaDto in vm.workAreas.Where(c => c.FloorId == floorVM.Id).ToList())
|
||||
{
|
||||
WorkAreaVM workAreaVM = new WorkAreaVM() { Id = workAreaDto.Id, AreaName = workAreaDto.AreaName, WorkItems = new List<WorkItemVM>() };
|
||||
|
||||
if (vm.workItems != null)
|
||||
{
|
||||
foreach (WorkItem workItemDto in vm.workItems.Where(c => c.WorkAreaId == workAreaDto.Id).ToList())
|
||||
{
|
||||
WorkItemVM workItemVM = new WorkItemVM() { WorkItemId = workItemDto.Id, WorkItem = workItemDto };
|
||||
|
||||
workItemVM.WorkItem.WorkArea = new WorkArea();
|
||||
|
||||
if (workItemVM.WorkItem.ActivityMaster != null)
|
||||
{
|
||||
workItemVM.WorkItem.ActivityMaster.Tenant = new Tenant();
|
||||
}
|
||||
workItemVM.WorkItem.Tenant = new Tenant();
|
||||
|
||||
double todaysAssigned = 0;
|
||||
if (vm.Tasks != null)
|
||||
{
|
||||
var tasks = vm.Tasks.Where(t => t.WorkItemId == workItemDto.Id).ToList();
|
||||
foreach (TaskAllocation task in tasks)
|
||||
{
|
||||
todaysAssigned += task.PlannedTask;
|
||||
}
|
||||
}
|
||||
workItemVM.TodaysAssigned = todaysAssigned;
|
||||
|
||||
workAreaVM.WorkItems.Add(workItemVM);
|
||||
}
|
||||
}
|
||||
|
||||
floorVM.WorkAreas.Add(workAreaVM);
|
||||
}
|
||||
}
|
||||
|
||||
buildVM.Floors.Add(floorVM);
|
||||
}
|
||||
}
|
||||
projectVM.Buildings.Add(buildVM);
|
||||
}
|
||||
}
|
||||
return Ok(ApiResponse<object>.SuccessResponse(projectVM, "Success.", 200));
|
||||
}
|
||||
|
||||
|
||||
// Step 6: Map and return result
|
||||
var projectVM = GetProjectViewModel(project);
|
||||
_logger.LogInfo("Project details fetched successfully. ProjectId: {ProjectId}", id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(projectVM, "Project details fetched successfully", 200));
|
||||
}
|
||||
|
||||
private async Task<ProjectDetailsVM> GetProjectViewModel(Guid? id, Project project)
|
||||
private ProjectVM GetProjectViewModel(Project project)
|
||||
{
|
||||
ProjectDetailsVM vm = new ProjectDetailsVM();
|
||||
|
||||
// List<Building> buildings = _unitOfWork.Building.GetAll(c => c.ProjectId == id).ToList();
|
||||
List<Building> buildings = await _context.Buildings.Where(c => c.ProjectId == id).ToListAsync();
|
||||
List<Guid> idList = buildings.Select(o => o.Id).ToList();
|
||||
// List<Floor> floors = _unitOfWork.Floor.GetAll(c => idList.Contains(c.Id)).ToList();
|
||||
List<Floor> floors = await _context.Floor.Where(c => idList.Contains(c.BuildingId)).ToListAsync();
|
||||
idList = floors.Select(o => o.Id).ToList();
|
||||
//List<WorkArea> workAreas = _unitOfWork.WorkArea.GetAll(c => idList.Contains(c.Id), includeProperties: "WorkItems,WorkItems.ActivityMaster").ToList();
|
||||
|
||||
List<WorkArea> workAreas = await _context.WorkAreas.Where(c => idList.Contains(c.FloorId)).ToListAsync();
|
||||
|
||||
idList = workAreas.Select(o => o.Id).ToList();
|
||||
List<WorkItem> workItems = await _context.WorkItems.Include(c => c.WorkCategoryMaster).Where(c => idList.Contains(c.WorkAreaId)).Include(c => c.ActivityMaster).ToListAsync();
|
||||
// List <WorkItem> workItems = _unitOfWork.WorkItem.GetAll(c => idList.Contains(c.WorkAreaId), includeProperties: "ActivityMaster").ToList();
|
||||
idList = workItems.Select(t => t.Id).ToList();
|
||||
List<TaskAllocation> tasks = await _context.TaskAllocations.Where(t => idList.Contains(t.WorkItemId) && t.AssignmentDate.Date == DateTime.UtcNow.Date).ToListAsync();
|
||||
vm.project = project;
|
||||
vm.buildings = buildings;
|
||||
vm.floors = floors;
|
||||
vm.workAreas = workAreas;
|
||||
vm.workItems = workItems;
|
||||
vm.Tasks = tasks;
|
||||
return vm;
|
||||
return new ProjectVM
|
||||
{
|
||||
Id = project.Id,
|
||||
Name = project.Name,
|
||||
ShortName = project.ShortName,
|
||||
StartDate = project.StartDate,
|
||||
EndDate = project.EndDate,
|
||||
ProjectStatus = project.ProjectStatus,
|
||||
ContactPerson = project.ContactPerson,
|
||||
ProjectAddress = project.ProjectAddress,
|
||||
};
|
||||
}
|
||||
|
||||
private Guid GetTenantId()
|
||||
@ -594,6 +541,116 @@ namespace MarcoBMS.Services.Controllers
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("infra-details/{projectId}")]
|
||||
public async Task<IActionResult> GetInfraDetails(Guid projectId)
|
||||
{
|
||||
_logger.LogInfo("GetInfraDetails called for ProjectId: {ProjectId}", projectId);
|
||||
|
||||
// Step 1: Get logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
// Step 2: Check project-specific permission
|
||||
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.ToString());
|
||||
if (!hasProjectPermission)
|
||||
{
|
||||
_logger.LogWarning("Project access denied for EmployeeId: {EmployeeId} on ProjectId: {ProjectId}", loggedInEmployee.Id, projectId);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "You don't have access to this project", 403));
|
||||
}
|
||||
|
||||
// Step 3: Check 'ViewInfra' permission
|
||||
var hasViewInfraPermission = await _permission.HasPermission(ViewInfra, loggedInEmployee.Id);
|
||||
if (!hasViewInfraPermission)
|
||||
{
|
||||
_logger.LogWarning("ViewInfra permission denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "You don't have access to view infra", 403));
|
||||
}
|
||||
|
||||
// Step 4: Fetch buildings for the project
|
||||
var buildings = await _context.Buildings
|
||||
.Where(b => b.ProjectId == projectId)
|
||||
.ToListAsync();
|
||||
|
||||
var buildingIds = buildings.Select(b => b.Id).ToList();
|
||||
|
||||
// Step 5: Fetch floors associated with the buildings
|
||||
var floors = await _context.Floor
|
||||
.Where(f => buildingIds.Contains(f.BuildingId))
|
||||
.ToListAsync();
|
||||
|
||||
var floorIds = floors.Select(f => f.Id).ToList();
|
||||
|
||||
// Step 6: Fetch work areas associated with the floors
|
||||
var workAreas = await _context.WorkAreas
|
||||
.Where(wa => floorIds.Contains(wa.FloorId))
|
||||
.ToListAsync();
|
||||
|
||||
// Step 7: Build the infra hierarchy (Building > Floors > Work Areas)
|
||||
var infraVM = buildings.Select(b =>
|
||||
{
|
||||
var selectedFloors = floors
|
||||
.Where(f => f.BuildingId == b.Id)
|
||||
.Select(f => new
|
||||
{
|
||||
Id = f.Id,
|
||||
FloorName = f.FloorName,
|
||||
WorkAreas = workAreas
|
||||
.Where(wa => wa.FloorId == f.Id)
|
||||
.Select(wa => new { wa.Id, wa.AreaName })
|
||||
.ToList()
|
||||
}).ToList();
|
||||
|
||||
return new
|
||||
{
|
||||
Id = b.Id,
|
||||
BuildingName = b.Name,
|
||||
Floors = selectedFloors
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
_logger.LogInfo("Infra details fetched successfully for ProjectId: {ProjectId}, EmployeeId: {EmployeeId}, Buildings: {Count}",
|
||||
projectId, loggedInEmployee.Id, infraVM.Count);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(infraVM, "Infra details fetched successfully", 200));
|
||||
}
|
||||
|
||||
[HttpGet("tasks/{workAreaId}")]
|
||||
public async Task<IActionResult> GetWorkItems(Guid workAreaId)
|
||||
{
|
||||
_logger.LogInfo("GetWorkItems called for WorkAreaId: {WorkAreaId}", workAreaId);
|
||||
|
||||
// Step 1: Get the currently logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
// Step 2: Check if the employee has ViewInfra permission
|
||||
var hasViewInfraPermission = await _permission.HasPermission(ViewInfra, loggedInEmployee.Id);
|
||||
if (!hasViewInfraPermission)
|
||||
{
|
||||
_logger.LogWarning("ViewInfra permission denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to view infrastructure", 403));
|
||||
}
|
||||
|
||||
// Step 3: Check if the specified Work Area exists
|
||||
var isWorkAreaExist = await _context.WorkAreas.AnyAsync(wa => wa.Id == workAreaId);
|
||||
if (!isWorkAreaExist)
|
||||
{
|
||||
_logger.LogWarning("Work Area not found for WorkAreaId: {WorkAreaId}", workAreaId);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Work Area not found", "Work Area not found in database", 404));
|
||||
}
|
||||
|
||||
// Step 4: Fetch WorkItems with related Activity and Work Category data
|
||||
var workItems = await _context.WorkItems
|
||||
.Include(wi => wi.ActivityMaster)
|
||||
.Include(wi => wi.WorkCategoryMaster)
|
||||
.Where(wi => wi.WorkAreaId == workAreaId)
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInfo("{Count} work items fetched successfully for WorkAreaId: {WorkAreaId}", workItems.Count, workAreaId);
|
||||
|
||||
// Step 5: Return result
|
||||
return Ok(ApiResponse<object>.SuccessResponse(workItems, $"{workItems.Count} records of tasks fetched successfully", 200));
|
||||
}
|
||||
|
||||
[HttpPost("task")]
|
||||
public async Task<IActionResult> CreateProjectTask(List<WorkItemDot> workItemDtos)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user