using Marco.Pms.DataAccess.Data; 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; using Marco.Pms.Model.ViewModels.Employee; using MarcoBMS.Services.Helpers; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace MarcoBMS.Services.Controllers { [Route("api/[controller]")] [ApiController] [Authorize] public class ProjectController : ControllerBase { //private readonly IUnitOfWork _unitOfWork; private readonly ApplicationDbContext _context; private ApplicationUser _applicationUser; // private readonly IProjectRepository _projectrepo; private readonly UserManager _userManager; private readonly UserHelper _userHelper; public ProjectController(UserManager userManager, ApplicationDbContext context, UserHelper userHelper) { //_unitOfWork = unitOfWork; _context = context; //_projectrepo = projectrepo; _userManager = userManager; _userHelper = userHelper; } [HttpGet("list")] public async Task GetAll() { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } var tenantId = _userHelper.GetTenantId(); List projects = await _context.Projects.Where(c=>c.TenantId == _userHelper.GetTenantId()).ToListAsync(); List response = new List(); foreach (var project in projects) { var result = project.ToProjectListVMFromProject(); var team = await _context.ProjectAllocations.Where(p => p.TenantId == tenantId && p.ProjectId == project.Id && p.IsActive == true).ToListAsync(); result.TeamSize = team.Count(); List buildings = await _context.Buildings.Where(b => b.ProjectId == project.Id && b.TenantId == tenantId).ToListAsync(); List idList = buildings.Select(b => b.Id).ToList(); List floors = await _context.Floor.Where(f => idList.Contains(f.BuildingId) && f.TenantId == tenantId).ToListAsync(); idList = floors.Select(f => f.Id).ToList(); List workAreas = await _context.WorkAreas.Where(a => idList.Contains(a.FloorId) && a.TenantId == tenantId).ToListAsync(); idList = workAreas.Select(a => a.Id).ToList(); List workItems = await _context.WorkItems.Where(i => idList.Contains(i.WorkAreaId) && i.TenantId == tenantId).Include(i => i.ActivityMaster).ToListAsync(); double completedTask = 0; double plannedTask = 0; foreach (var workItem in workItems) { completedTask += workItem.CompletedWork; plannedTask += workItem.PlannedWork; } result.PlannedWork = plannedTask; result.CompletedWork = completedTask; response.Add(result); } return Ok(ApiResponse.SuccessResponse(response, "Success.", 200)); } [HttpGet("get/{id:int}")] public async Task Get([FromRoute] int id) { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } var project = await _context.Projects.Where(c => c.TenantId == _userHelper.GetTenantId() && c.Id == id).SingleOrDefaultAsync(); return Ok(ApiResponse.SuccessResponse(project, "Success.", 200)); } [HttpGet("details/{id:int}")] public async Task Details([FromRoute] int id) { // ProjectDetailsVM vm = new ProjectDetailsVM(); if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.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); if (project == null) { return NotFound(ApiResponse.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(); projectVM.Id = vm.project.Id; projectVM.Name = vm.project.Name; 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(); foreach (Building build in vm.buildings) { BuildingVM buildVM = new BuildingVM() { Id = build.Id, Description = build.Description, Name = build.Name }; buildVM.Floors = new List(); 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(); 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() }; 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 = null; workItemVM.WorkItem.ActivityMaster.Tenant = null; workItemVM.WorkItem.Tenant = null; workAreaVM.WorkItems.Add(workItemVM); } floorVM.WorkAreas.Add(workAreaVM); } buildVM.Floors.Add(floorVM); } projectVM.Buildings.Add(buildVM); } return Ok(ApiResponse.SuccessResponse(projectVM, "Success.", 200)); } } private async Task GetProjectViewModel(int? id, Project project) { ProjectDetailsVM vm = new ProjectDetailsVM(); // List buildings = _unitOfWork.Building.GetAll(c => c.ProjectId == id).ToList(); List buildings = await _context.Buildings.Where(c => c.ProjectId == id).ToListAsync(); List idList = buildings.Select(o => o.Id).ToList(); // List floors = _unitOfWork.Floor.GetAll(c => idList.Contains(c.Id)).ToList(); List floors = await _context.Floor.Where(c => idList.Contains(c.BuildingId)).ToListAsync(); idList = floors.Select(o => o.Id).ToList(); //List workAreas = _unitOfWork.WorkArea.GetAll(c => idList.Contains(c.Id), includeProperties: "WorkItems,WorkItems.ActivityMaster").ToList(); List workAreas = await _context.WorkAreas.Where(c => idList.Contains(c.FloorId)).ToListAsync(); idList = workAreas.Select(o => o.Id).ToList(); List workItems = await _context.WorkItems.Where(c => idList.Contains(c.WorkAreaId)).Include(c=>c.ActivityMaster).ToListAsync(); // List workItems = _unitOfWork.WorkItem.GetAll(c => idList.Contains(c.WorkAreaId), includeProperties: "ActivityMaster").ToList(); vm.project = project; vm.buildings = buildings; vm.floors = floors; vm.workAreas = workAreas; vm.workItems = workItems; return vm; } private int GetTenantId() { return _userHelper.GetTenantId(); //var tenant = User.FindFirst("TenantId")?.Value; //return (tenant != null ? Convert.ToInt32(tenant) : 1); } [HttpPost] public async Task Create([FromBody] CreateProjectDto projectDto) { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } int TenantId = GetTenantId(); var project = projectDto.ToProjectFromCreateProjectDto(TenantId); _context.Projects.Add(project); await _context.SaveChangesAsync(); return Ok(ApiResponse.SuccessResponse(project.ToProjectDto(), "Success.", 200)); } [HttpPut] [Route("update/{id:int}")] public async Task Update([FromRoute] int id, [FromBody] UpdateProjectDto updateProjectDto) { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } try { int TenantId = GetTenantId(); updateProjectDto.TenantId = TenantId; Project project = updateProjectDto.ToProjectFromUpdateProjectDto(TenantId,id); _context.Projects.Update(project); await _context.SaveChangesAsync(); return Ok(ApiResponse.SuccessResponse(project.ToProjectDto(), "Success.", 200)); } catch (Exception ex) { return BadRequest(ApiResponse.ErrorResponse(ex.Message, ex, 400)); } } //[HttpPost("assign-employee")] //public async Task AssignEmployee(int? allocationid, int employeeId, int projectId) //{ // var employee = await _context.Employees.FindAsync(employeeId); // var project = _projectrepo.Get(c => c.Id == projectId); // if (employee == null || project == null) // { // return NotFound(); // } // // Logic to add the product to a new table (e.g., selected products) // if (allocationid == null) // { // // Add allocation // ProjectAllocation allocation = new ProjectAllocation() // { // EmployeeId = employeeId, // ProjectId = project.Id, // AllocationDate = DateTime.UtcNow, // //EmployeeRole = employee.Rol // TenantId = project.TenantId // }; // _unitOfWork.ProjectAllocation.CreateAsync(allocation); // } // else // { // //remove allocation // var allocation = await _context.ProjectAllocations.FindAsync(allocationid); // if (allocation != null) // { // allocation.ReAllocationDate = DateTime.UtcNow; // _unitOfWork.ProjectAllocation.UpdateAsync(allocation.Id, allocation); // } // else // { // return NotFound(); // } // } // return Ok(); //} [HttpGet] [Route("employees/get/{projectid?}/{includeInactive?}")] public async Task GetEmployeeByProjectID(int? projectid, bool? includeInactive = false) { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } int TenantId = GetTenantId(); if (projectid != null) { // Fetch assigned project List result = new List(); if ((bool)includeInactive) { result = await (from rpm in _context.Employees.Include(c => c.JobRole) join fp in _context.ProjectAllocations.Where(c => c.TenantId == TenantId && c.ProjectId == projectid) on rpm.Id equals fp.EmployeeId select rpm).ToListAsync(); }else { result = await (from rpm in _context.Employees.Include(c => c.JobRole) join fp in _context.ProjectAllocations.Where(c => c.TenantId == TenantId && c.ProjectId == projectid && c.IsActive == true) on rpm.Id equals fp.EmployeeId select rpm).ToListAsync(); } List resultVM = new List(); foreach (Employee employee in result) { EmployeeVM vm = employee.ToEmployeeVMFromEmployee(); resultVM.Add(vm); } return Ok(ApiResponse.SuccessResponse(resultVM, "Success.", 200)); } else { return NotFound(ApiResponse.ErrorResponse("Invalid Input Parameter", 404)); } } [HttpGet] [Route("allocation/{projectId:int}")] public async Task GetProjectAllocation(int? projectId) { if (!ModelState.IsValid) { var errors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } int TenantId = GetTenantId(); var employees = await _context.ProjectAllocations.Where(c => c.TenantId == TenantId && c.ProjectId == projectId).Include(e => e.Employee).Include(e => e.Employee.JobRole).Select(e => new { ID = e.Id, EmployeeId = e.EmployeeId, ProjectId = e.ProjectId, AllocationDate = e.AllocationDate, ReAllocationDate = e.ReAllocationDate, FirstName = e.Employee.FirstName, LastName = e.Employee.LastName, MiddleName = e.Employee.MiddleName, IsActive = e.IsActive, JobRoleId = (e.JobRoleId != null ? e.JobRoleId : e.Employee.JobRoleId) }).ToListAsync(); return Ok(ApiResponse.SuccessResponse(employees, "Success.", 200)); } [HttpPost("allocation")] public async Task ManageAllocation(List projectAllocationDot) { if (projectAllocationDot != null) { int TenentID = GetTenantId(); foreach (var item in projectAllocationDot) { try { ProjectAllocation projectAllocation = item.ToProjectAllocationFromProjectAllocationDto(TenentID); ProjectAllocation projectAllocationFromDb = await _context.ProjectAllocations.Where(c => c.EmployeeId == projectAllocation.EmployeeId && c.ProjectId == projectAllocation.ProjectId && c.ReAllocationDate == null && c.TenantId == TenentID).SingleOrDefaultAsync(); if (projectAllocationFromDb != null) { _context.ProjectAllocations.Attach(projectAllocationFromDb); if (item.Status) { projectAllocationFromDb.JobRoleId = projectAllocation.JobRoleId; ; projectAllocationFromDb.IsActive = true; _context.Entry(projectAllocationFromDb).Property(e => e.JobRoleId).IsModified = true; _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; } else { projectAllocationFromDb.ReAllocationDate = DateTime.Now; projectAllocationFromDb.IsActive = false; _context.Entry(projectAllocationFromDb).Property(e => e.ReAllocationDate).IsModified = true; _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; } await _context.SaveChangesAsync(); } else { projectAllocation.AllocationDate = DateTime.Now; projectAllocation.IsActive = true; _context.ProjectAllocations.Add(projectAllocation); await _context.SaveChangesAsync(); } } catch (Exception ex) { return Ok(ApiResponse.ErrorResponse(ex.Message,ex, 400)); } } return Ok(ApiResponse.SuccessResponse(null, "Data saved successfully.", 200)); } return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid." , 400)); } [HttpPost("task")] public async Task CreateProjectTask(List workItemDot) { List workItems = new List { }; if (workItemDot != null) { foreach (var item in workItemDot) { item.TenantId = GetTenantId(); WorkItem workItem = item.ToWorkItemFromWorkItemDto(); if (item.Id > 0) { //update _context.WorkItems.Update(workItem); await _context.SaveChangesAsync(); } else { //create _context.WorkItems.Add(workItem); await _context.SaveChangesAsync(); } var result = new WorkItemVM { WorkItemId = workItem.Id, WorkItem = workItem }; workItems.Add(result); } var activity = await _context.ActivityMasters.ToListAsync(); return Ok(ApiResponse.SuccessResponse(workItems, "Data saved successfully.", 200)); } return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400)); } [HttpPost("manage-infra")] public async Task ManageProjectInfra(List infraDots) { var responseData = new InfraVM{ }; if (infraDots != null) { foreach (var item in infraDots) { if (item.Building != null) { Building building = item.Building.ToBuildingFromBuildingDto(); building.TenantId = GetTenantId(); if (item.Building.Id == 0) { //create _context.Buildings.Add(building); await _context.SaveChangesAsync(); responseData.building = building; } else { //update _context.Buildings.Update(building); await _context.SaveChangesAsync(); responseData.building = building; } } if (item.Floor != null) { Floor floor = item.Floor.ToFloorFromFloorDto(); floor.TenantId = GetTenantId(); if (item.Floor.Id == 0) { //create _context.Floor.Add(floor); await _context.SaveChangesAsync(); responseData.floor = floor; } else { //update _context.Floor.Update(floor); await _context.SaveChangesAsync(); responseData.floor = floor; } } if (item.WorkArea != null) { WorkArea workArea = item.WorkArea.ToWorkAreaFromWorkAreaDto(); workArea.TenantId = GetTenantId(); if (item.WorkArea.Id == 0) { //create _context.WorkAreas.Add(workArea); await _context.SaveChangesAsync(); responseData.workArea = workArea; } else { //update _context.WorkAreas.Update(workArea); await _context.SaveChangesAsync(); responseData.workArea = workArea; } } } return Ok(ApiResponse.SuccessResponse(responseData, "Data saved successfully.", 200)); } return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Infra Details are not valid.", 400)); } } }