From d38bc4752af119b0c025e2a300c91ab93f4ec150 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Fri, 19 Sep 2025 14:15:41 +0530 Subject: [PATCH 1/2] Added the API to get list of services according to the project and logged in employee --- .../ViewModels/Activities/ActivityVM.cs | 6 +- .../Master/ActivityGroupMasterVM.cs | 1 - .../Controllers/OrganizationController.cs | 22 +++++- .../Controllers/ProjectController.cs | 8 ++ Marco.Pms.Services/Service/MasterService.cs | 1 + Marco.Pms.Services/Service/ProjectServices.cs | 79 +++++++++++++++++++ .../ServiceInterfaces/IProjectServices.cs | 1 + 7 files changed, 109 insertions(+), 9 deletions(-) diff --git a/Marco.Pms.Model/ViewModels/Activities/ActivityVM.cs b/Marco.Pms.Model/ViewModels/Activities/ActivityVM.cs index af2da26..4ec9686 100644 --- a/Marco.Pms.Model/ViewModels/Activities/ActivityVM.cs +++ b/Marco.Pms.Model/ViewModels/Activities/ActivityVM.cs @@ -1,15 +1,11 @@ -using Marco.Pms.Model.ViewModels.Master; - -namespace Marco.Pms.Model.ViewModels.Activities +namespace Marco.Pms.Model.ViewModels.Activities { public class ActivityVM { public Guid Id { get; set; } public string? ActivityName { get; set; } - public string? UnitOfMeasurement { get; set; } public List? CheckLists { get; set; } - public ActivityGroupMasterVM? ActivityGroup { get; set; } public bool IsActive { get; set; } = true; public bool IsSystem { get; set; } = false; } diff --git a/Marco.Pms.Model/ViewModels/Master/ActivityGroupMasterVM.cs b/Marco.Pms.Model/ViewModels/Master/ActivityGroupMasterVM.cs index fc3d41e..e82bd7b 100644 --- a/Marco.Pms.Model/ViewModels/Master/ActivityGroupMasterVM.cs +++ b/Marco.Pms.Model/ViewModels/Master/ActivityGroupMasterVM.cs @@ -5,7 +5,6 @@ public Guid Id { get; set; } public string? Name { get; set; } public string? Description { get; set; } - public ServiceMasterVM? Service { get; set; } public bool IsSystem { get; set; } public bool IsActive { get; set; } } diff --git a/Marco.Pms.Services/Controllers/OrganizationController.cs b/Marco.Pms.Services/Controllers/OrganizationController.cs index 8928983..796e1ee 100644 --- a/Marco.Pms.Services/Controllers/OrganizationController.cs +++ b/Marco.Pms.Services/Controllers/OrganizationController.cs @@ -256,6 +256,14 @@ namespace Marco.Pms.Services.Controllers .Where(sp => model.ServiceIds.Contains(sp.ServiceId) && sp.ProjectId == model.ProjectId && sp.IsActive).ToListAsync(); }); + var projectOrganizationsTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.ProjectOrgMappings + .Include(po => po.ProjectService) + .Where(po => po.ProjectService != null && model.ServiceIds.Contains(po.ProjectService.ServiceId) && po.ProjectService.ProjectId == model.ProjectId).ToListAsync(); + }); + var serviceTask = Task.Run(async () => { await using var context = await _dbContextFactory.CreateDbContextAsync(); @@ -299,13 +307,15 @@ namespace Marco.Pms.Services.Controllers && p.OrganizationTypeId == ServiceProvider); }); - await Task.WhenAll(organizationTask, parentorganizationTask, projectTask, projectServicesTask, isPMCTask, isServiceProviderTask, serviceTask, organizationTypeTask); + await Task.WhenAll(organizationTask, parentorganizationTask, projectTask, projectServicesTask, isPMCTask, isServiceProviderTask, + serviceTask, organizationTypeTask, projectOrganizationsTask); var services = serviceTask.Result; var organizationType = organizationTypeTask.Result; var organization = organizationTask.Result; var projectServices = projectServicesTask.Result; var parentorganization = parentorganizationTask.Result; + var projectOrganizations = projectOrganizationsTask.Result; var project = projectTask.Result; var isPMC = isPMCTask.Result; var isServiceProvider = isServiceProviderTask.Result; @@ -324,7 +334,7 @@ namespace Marco.Pms.Services.Controllers } var serviceProviderTenantMapping = await _context.TenantOrgMappings - .FirstOrDefaultAsync(spt => spt.OrganizationId == model.OrganizationId && spt.TenantId == project.TenantId); + .FirstOrDefaultAsync(spt => spt.OrganizationId == model.OrganizationId && spt.TenantId == project.TenantId && spt.IsActive); if (serviceProviderTenantMapping == null) { @@ -332,6 +342,7 @@ namespace Marco.Pms.Services.Controllers { OrganizationId = organization.Id, SPRID = organization.SPRID, + AssignedDate = DateTime.UtcNow, IsActive = true, TenantId = project.TenantId }; @@ -374,7 +385,12 @@ namespace Marco.Pms.Services.Controllers AssignedDate = DateTime.UtcNow, TenantId = project.TenantId }; - projectOrgMappings.Add(projectOrgMapping); + var projectOrganization = projectOrganizations + .FirstOrDefault(po => po.ProjectService != null && po.ProjectService.ProjectId == project.Id && po.ProjectService.ServiceId == serviceId); + if (projectOrganization == null) + { + projectOrgMappings.Add(projectOrgMapping); + } } _context.ProjectOrgMappings.AddRange(projectOrgMappings); diff --git a/Marco.Pms.Services/Controllers/ProjectController.cs b/Marco.Pms.Services/Controllers/ProjectController.cs index d786fe5..8346a98 100644 --- a/Marco.Pms.Services/Controllers/ProjectController.cs +++ b/Marco.Pms.Services/Controllers/ProjectController.cs @@ -502,6 +502,14 @@ namespace MarcoBMS.Services.Controllers #region =================================================================== Assign Service APIs =================================================================== + [HttpGet("get/assigned/services/{projectId}")] + public async Task AssignServiceToProject(Guid projectId) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _projectServices.GetAssignedServiceToProjectAsync(projectId, tenantId, loggedInEmployee); + + return StatusCode(response.StatusCode, response); + } [HttpPost("assign/service")] public async Task AssignServiceToProject([FromBody] AssignServiceDto model) { diff --git a/Marco.Pms.Services/Service/MasterService.cs b/Marco.Pms.Services/Service/MasterService.cs index 0b6ab1b..7351d3c 100644 --- a/Marco.Pms.Services/Service/MasterService.cs +++ b/Marco.Pms.Services/Service/MasterService.cs @@ -213,6 +213,7 @@ namespace Marco.Pms.Services.Service //} #endregion + #region =================================================================== Services APIs =================================================================== public async Task> GetServicesAsync(Employee loggedInEmployee, Guid tenantId) { diff --git a/Marco.Pms.Services/Service/ProjectServices.cs b/Marco.Pms.Services/Service/ProjectServices.cs index 2024e8c..22a9f21 100644 --- a/Marco.Pms.Services/Service/ProjectServices.cs +++ b/Marco.Pms.Services/Service/ProjectServices.cs @@ -7,6 +7,7 @@ using Marco.Pms.Model.Dtos.Projects; using Marco.Pms.Model.Dtos.Util; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.Master; using Marco.Pms.Model.MongoDBModels.Project; using Marco.Pms.Model.OrganizationModel; using Marco.Pms.Model.Projects; @@ -1834,16 +1835,84 @@ namespace Marco.Pms.Services.Service #region =================================================================== Assign Service APIs =================================================================== + public async Task> GetAssignedServiceToProjectAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee) + { + try + { + using var scope = _serviceScopeFactory.CreateScope(); + var _permission = scope.ServiceProvider.GetRequiredService(); + + var project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId); + if (project == null) + { + return ApiResponse.ErrorResponse("Project not found", "Project not found in database", 404); + } + + var hasPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId); + if (!hasPermission) + { + _logger.LogWarning("Access DENIED for user {UserId} attempting to update project {ProjectId}.", loggedInEmployee.Id, projectId); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to modify this project.", 403); + } + + List services = new List(); + if (project.PromoterId == loggedInEmployee.OrganizationId && project.PMCId == loggedInEmployee.OrganizationId) + { + var projectServices = await _context.ProjectServiceMappings + .Include(ps => ps.Service) + .Where(ps => ps.ProjectId == projectId && ps.Service != null && ps.TenantId == tenantId && ps.IsActive) + .ToListAsync(); + services = projectServices.Select(ps => ps.Service!).Distinct().ToList(); + } + else + { + var orgProjectMapping = await _context.ProjectOrgMappings + .Include(po => po.ProjectService) + .ThenInclude(ps => ps!.Service) + .Where(po => po.OrganizationId == loggedInEmployee.OrganizationId && po.ProjectService != null + && po.ProjectService.IsActive && po.ProjectService.ProjectId == projectId && po.ProjectService.Service != null) + .ToListAsync(); + + services = orgProjectMapping.Select(po => po.ProjectService!.Service!).Distinct().ToList(); + } + var response = _mapper.Map>(services); + + return ApiResponse.SuccessResponse(response, "Services has been deassigned to the project", 200); + } + catch (DbUpdateException dbEx) + { + //await transaction.RollbackAsync(); + + _logger.LogError(dbEx, "Database Exception has been occured, While deassigning the sevice to the project"); + return ApiResponse.ErrorResponse("Internal error", "An database exception has been occured", 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception has been occured, While deassigning the sevice to the project"); + return ApiResponse.ErrorResponse("Internal error", "An internal exception has been occured", 500); + } + } public async Task> AssignServiceToProjectAsync(AssignServiceDto model, Guid tenantId, Employee loggedInEmployee) { await using var transaction = await _context.Database.BeginTransactionAsync(); try { + using var scope = _serviceScopeFactory.CreateScope(); + var _permission = scope.ServiceProvider.GetRequiredService(); + var project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId); if (project == null) { return ApiResponse.ErrorResponse("Project not found", "Project not found in database", 404); } + + var hasPermission = await _permission.HasProjectPermission(loggedInEmployee, model.ProjectId); + if (!hasPermission) + { + _logger.LogWarning("Access DENIED for user {UserId} attempting to update project {ProjectId}.", loggedInEmployee.Id, model.ProjectId); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to modify this project.", 403); + } + var todaysDate = DateTime.UtcNow.Date; var projectServicesTask = Task.Run(async () => @@ -1915,11 +1984,21 @@ namespace Marco.Pms.Services.Service await using var transaction = await _context.Database.BeginTransactionAsync(); try { + using var scope = _serviceScopeFactory.CreateScope(); + var _permission = scope.ServiceProvider.GetRequiredService(); + var project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == model.ProjectId && p.TenantId == tenantId); if (project == null) { return ApiResponse.ErrorResponse("Project not found", "Project not found in database", 404); } + + var hasPermission = await _permission.HasProjectPermission(loggedInEmployee, model.ProjectId); + if (!hasPermission) + { + _logger.LogWarning("Access DENIED for user {UserId} attempting to update project {ProjectId}.", loggedInEmployee.Id, model.ProjectId); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to modify this project.", 403); + } var todaysDate = DateTime.UtcNow.Date; var projectServicesTask = Task.Run(async () => diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IProjectServices.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IProjectServices.cs index 8ec9aae..d8eb23f 100644 --- a/Marco.Pms.Services/Service/ServiceInterfaces/IProjectServices.cs +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IProjectServices.cs @@ -43,6 +43,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces Task> GetEmployeeToWhomProjectLevelAssignedAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee); Task> GetAllPermissionFroProjectAsync(Guid projectId, Employee loggedInEmployee, Guid tenantId); + Task> GetAssignedServiceToProjectAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee); Task> AssignServiceToProjectAsync(AssignServiceDto model, Guid tenantId, Employee loggedInEmployee); Task> DeassignServiceToProjectAsync(DeassignServiceDto model, Guid tenantId, Employee loggedInEmployee); From 009ac36e38b3d5f062d40b7d3e4f6062960ea285 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Fri, 19 Sep 2025 14:22:14 +0530 Subject: [PATCH 2/2] Changed the response message for get services API --- Marco.Pms.Services/Service/ProjectServices.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marco.Pms.Services/Service/ProjectServices.cs b/Marco.Pms.Services/Service/ProjectServices.cs index 22a9f21..b0d8188 100644 --- a/Marco.Pms.Services/Service/ProjectServices.cs +++ b/Marco.Pms.Services/Service/ProjectServices.cs @@ -1877,7 +1877,7 @@ namespace Marco.Pms.Services.Service } var response = _mapper.Map>(services); - return ApiResponse.SuccessResponse(response, "Services has been deassigned to the project", 200); + return ApiResponse.SuccessResponse(response, "Successfully fetched the services for this project", 200); } catch (DbUpdateException dbEx) {