From 11b54debc6eaa55b302ab39578ca03dbf97db228 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 7 Jul 2025 10:04:11 +0530 Subject: [PATCH] Implemented the methods for deleting permission am asigned project from caches for certien employee --- Marco.Pms.CacheHelper/EmployeeCache.cs | 60 ++++++++++++++----- Marco.Pms.CacheHelper/ProjectCache.cs | 55 ++++++++++------- .../EmployeePermissionMongoDB.cs | 2 +- .../MongoDBModels/ProjectMongoDB.cs | 2 +- .../MongoDBModels/WorkItemMongoDB.cs | 9 +-- .../Controllers/RolesController.cs | 4 ++ .../Helpers/CacheUpdateHelper.cs | 57 +++++++++++------- Marco.Pms.Services/Helpers/ProjectsHelper.cs | 21 ++++++- 8 files changed, 144 insertions(+), 66 deletions(-) diff --git a/Marco.Pms.CacheHelper/EmployeeCache.cs b/Marco.Pms.CacheHelper/EmployeeCache.cs index 7d75407..5c86e6f 100644 --- a/Marco.Pms.CacheHelper/EmployeeCache.cs +++ b/Marco.Pms.CacheHelper/EmployeeCache.cs @@ -22,31 +22,47 @@ namespace Marco.Pms.CacheHelper } public async Task AddApplicationRoleToCache(Guid employeeId, List roleIds) { - var newRoleIds = roleIds.Select(r => r.ToString()).ToList(); - var newPermissionIds = await _context.RolePermissionMappings + // 1. Guard Clause: Avoid unnecessary database work if there are no roles to add. + if (roleIds == null || !roleIds.Any()) + { + return false; // Nothing to add, so the operation did not result in a change. + } + + // 2. Perform database queries concurrently for better performance. + var employeeIdString = employeeId.ToString(); + + Task> getPermissionIdsTask = _context.RolePermissionMappings .Where(rp => roleIds.Contains(rp.ApplicationRoleId)) .Select(p => p.FeaturePermissionId.ToString()) .Distinct() .ToListAsync(); - var filter = Builders.Filter.Eq(e => e.EmployeeId, employeeId.ToString()); + // 3. Prepare role IDs in parallel with the database query. + var newRoleIds = roleIds.Select(r => r.ToString()).ToList(); + + // 4. Await the database query result. + var newPermissionIds = await getPermissionIdsTask; + + // 5. Build a single, efficient update operation. + var filter = Builders.Filter.Eq(e => e.Id, employeeIdString); var update = Builders.Update .AddToSetEach(e => e.ApplicationRoleIds, newRoleIds) .AddToSetEach(e => e.PermissionIds, newPermissionIds); - var result = await _collection.UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); - if (result.MatchedCount == 0) - { - return false; - } - return true; + var options = new UpdateOptions { IsUpsert = true }; + + var result = await _collection.UpdateOneAsync(filter, update, options); + + // 6. Return a more accurate result indicating success for both updates and upserts. + // The operation is successful if an existing document was modified OR a new one was created. + return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null); } public async Task AddProjectsToCache(Guid employeeId, List projectIds) { var newprojectIds = projectIds.Select(p => p.ToString()).ToList(); - var filter = Builders.Filter.Eq(e => e.EmployeeId, employeeId.ToString()); + var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .AddToSetEach(e => e.ProjectIds, newprojectIds); @@ -60,7 +76,7 @@ namespace Marco.Pms.CacheHelper } public async Task> GetProjectsFromCache(Guid employeeId) { - var filter = Builders.Filter.Eq(e => e.EmployeeId, employeeId.ToString()); + var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var result = await _collection @@ -77,7 +93,7 @@ namespace Marco.Pms.CacheHelper } public async Task> GetPermissionsFromCache(Guid employeeId) { - var filter = Builders.Filter.Eq(e => e.EmployeeId, employeeId.ToString()); + var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var result = await _collection @@ -95,7 +111,21 @@ namespace Marco.Pms.CacheHelper public async Task ClearAllProjectIdsFromCache(Guid employeeId) { var filter = Builders.Filter - .Eq(e => e.EmployeeId, employeeId.ToString()); + .Eq(e => e.Id, employeeId.ToString()); + + var update = Builders.Update + .Set(e => e.ProjectIds, new List()); + + var result = await _collection.UpdateOneAsync(filter, update); + + if (result.MatchedCount == 0) + return false; + + return true; + } + public async Task ClearAllProjectIdsByRoleIdFromCache(Guid roleId) + { + var filter = Builders.Filter.AnyEq(e => e.ApplicationRoleIds, roleId.ToString()); var update = Builders.Update .Set(e => e.ProjectIds, new List()); @@ -110,7 +140,7 @@ namespace Marco.Pms.CacheHelper public async Task RemoveRoleIdFromCache(Guid employeeId, Guid roleId) { var filter = Builders.Filter - .Eq(e => e.EmployeeId, employeeId.ToString()); + .Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .Pull(e => e.ApplicationRoleIds, roleId.ToString()); @@ -128,7 +158,7 @@ namespace Marco.Pms.CacheHelper public async Task ClearAllPermissionIdsByEmployeeIDFromCache(Guid employeeId) { var filter = Builders.Filter - .Eq(e => e.EmployeeId, employeeId.ToString()); + .Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .Set(e => e.PermissionIds, new List()); diff --git a/Marco.Pms.CacheHelper/ProjectCache.cs b/Marco.Pms.CacheHelper/ProjectCache.cs index b667694..f60884f 100644 --- a/Marco.Pms.CacheHelper/ProjectCache.cs +++ b/Marco.Pms.CacheHelper/ProjectCache.cs @@ -11,19 +11,21 @@ namespace Marco.Pms.CacheHelper public class ProjectCache { private readonly ApplicationDbContext _context; - private readonly IMongoDatabase _mongoDB; - //private readonly ILoggingService _logger; + private readonly IMongoCollection _projetCollection; + private readonly IMongoCollection _taskCollection; public ProjectCache(ApplicationDbContext context, IConfiguration configuration) { var connectionString = configuration["MongoDB:ConnectionString"]; _context = context; var mongoUrl = new MongoUrl(connectionString); var client = new MongoClient(mongoUrl); // Your MongoDB connection string - _mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name + var mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name + _projetCollection = mongoDB.GetCollection("ProjectDetails"); + _taskCollection = mongoDB.GetCollection("WorkItemDetails"); } public async Task AddProjectDetailsToCache(Project project) { - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); + //_logger.LogInfo("[AddProjectDetails] Initiated for ProjectId: {ProjectId}", project.Id); @@ -145,7 +147,7 @@ namespace Marco.Pms.CacheHelper projectDetails.PlannedWork = totalPlannedWork; projectDetails.CompletedWork = totalCompletedWork; - await projectCollection.InsertOneAsync(projectDetails); + await _projetCollection.InsertOneAsync(projectDetails); //_logger.LogInfo("[AddProjectDetails] Project details inserted in MongoDB for ProjectId: {ProjectId}", project.Id); } public async Task UpdateProjectDetailsOnlyToCache(Project project) @@ -160,8 +162,6 @@ namespace Marco.Pms.CacheHelper //_logger.LogWarning("StatusMaster not found for ProjectStatusId: {StatusId}", project.ProjectStatusId); } - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); - // Build the update definition var updates = Builders.Update.Combine( Builders.Update.Set(r => r.Name, project.Name), @@ -178,7 +178,7 @@ namespace Marco.Pms.CacheHelper ); // Perform the update - var result = await projectCollection.UpdateOneAsync( + var result = await _projetCollection.UpdateOneAsync( filter: r => r.Id == project.Id.ToString(), update: updates ); @@ -194,7 +194,6 @@ namespace Marco.Pms.CacheHelper } public async Task GetProjectDetailsFromCache(Guid projectId) { - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); // Build filter and projection to exclude large 'Buildings' list var filter = Builders.Filter.Eq(p => p.Id, projectId.ToString()); @@ -203,7 +202,7 @@ namespace Marco.Pms.CacheHelper //_logger.LogInfo("Fetching project details for ProjectId: {ProjectId} from MongoDB", projectId); // Perform query - var project = await projectCollection + var project = await _projetCollection .Find(filter) .Project(projection) .FirstOrDefaultAsync(); @@ -214,16 +213,23 @@ namespace Marco.Pms.CacheHelper return null; } - //// Deserialize the result manually - //var project = BsonSerializer.Deserialize(result); - //_logger.LogInfo("Successfully fetched project details (excluding Buildings) for ProjectId: {ProjectId}", projectId); return project; } + public async Task?> GetProjectDetailsListFromCache(List projectIds) + { + List stringProjectIds = projectIds.Select(p => p.ToString()).ToList(); + var filter = Builders.Filter.In(p => p.Id, stringProjectIds); + var projection = Builders.Projection.Exclude(p => p.Buildings); + var projects = await _projetCollection + .Find(filter) + .Project(projection) + .ToListAsync(); + return projects; + } public async Task AddBuildngInfraToCache(Guid projectId, Building? building, Floor? floor, WorkArea? workArea, Guid? buildingId) { var stringProjectId = projectId.ToString(); - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); // Add Building if (building != null) @@ -241,7 +247,7 @@ namespace Marco.Pms.CacheHelper var filter = Builders.Filter.Eq(p => p.Id, stringProjectId); var update = Builders.Update.Push("Buildings", buildingMongo); - var result = await projectCollection.UpdateOneAsync(filter, update); + var result = await _projetCollection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) { @@ -271,7 +277,7 @@ namespace Marco.Pms.CacheHelper ); var update = Builders.Update.Push("Buildings.$.Floors", floorMongo); - var result = await projectCollection.UpdateOneAsync(filter, update); + var result = await _projetCollection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) { @@ -305,7 +311,7 @@ namespace Marco.Pms.CacheHelper var update = Builders.Update.Push("Buildings.$[b].Floors.$[f].WorkAreas", workAreaMongo); var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters }; - var result = await projectCollection.UpdateOneAsync(filter, update, updateOptions); + var result = await _projetCollection.UpdateOneAsync(filter, update, updateOptions); if (result.MatchedCount == 0) { @@ -323,7 +329,6 @@ namespace Marco.Pms.CacheHelper public async Task UpdateBuildngInfraToCache(Guid projectId, Building? building, Floor? floor, WorkArea? workArea, Guid? buildingId) { var stringProjectId = projectId.ToString(); - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); // Update Building if (building != null) @@ -338,7 +343,7 @@ namespace Marco.Pms.CacheHelper Builders.Update.Set("Buildings.$.Description", building.Description) ); - var result = await projectCollection.UpdateOneAsync(filter, update); + var result = await _projetCollection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) { @@ -363,7 +368,7 @@ namespace Marco.Pms.CacheHelper var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters }; var filter = Builders.Filter.Eq(p => p.Id, stringProjectId); - var result = await projectCollection.UpdateOneAsync(filter, update, updateOptions); + var result = await _projetCollection.UpdateOneAsync(filter, update, updateOptions); if (result.MatchedCount == 0) { @@ -389,7 +394,7 @@ namespace Marco.Pms.CacheHelper var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters }; var filter = Builders.Filter.Eq(p => p.Id, stringProjectId); - var result = await projectCollection.UpdateOneAsync(filter, update, updateOptions); + var result = await _projetCollection.UpdateOneAsync(filter, update, updateOptions); if (result.MatchedCount == 0) { @@ -408,13 +413,12 @@ namespace Marco.Pms.CacheHelper } public async Task?> GetBuildingInfraFromCache(Guid projectId) { - var projectCollection = _mongoDB.GetCollection("ProjectDetails"); // Filter by project ID var filter = Builders.Filter.Eq(p => p.Id, projectId.ToString()); // Project only the "Buildings" field from the document - var buildings = await projectCollection + var buildings = await _projetCollection .Find(filter) .Project(p => p.Buildings) .FirstOrDefaultAsync(); @@ -430,5 +434,10 @@ namespace Marco.Pms.CacheHelper return buildings; } + + + // ------------------------------------------------------- WorkItem ------------------------------------------------------- + + } } diff --git a/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs b/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs index f141798..49c514e 100644 --- a/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/EmployeePermissionMongoDB.cs @@ -5,7 +5,7 @@ namespace Marco.Pms.Model.MongoDBModels [BsonIgnoreExtraElements] public class EmployeePermissionMongoDB { - public string EmployeeId { get; set; } = string.Empty; + public string Id { get; set; } = string.Empty; // Employee ID public List ApplicationRoleIds { get; set; } = new List(); public List PermissionIds { get; set; } = new List(); public List ProjectIds { get; set; } = new List(); diff --git a/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs b/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs index 8bf1c9a..8b1612c 100644 --- a/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/ProjectMongoDB.cs @@ -2,7 +2,7 @@ { public class ProjectMongoDB { - public string? Id { get; set; } + public string Id { get; set; } = string.Empty; public string? Name { get; set; } public string? ShortName { get; set; } public string? ProjectAddress { get; set; } diff --git a/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs b/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs index dc7fdb9..71638a3 100644 --- a/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs +++ b/Marco.Pms.Model/MongoDBModels/WorkItemMongoDB.cs @@ -2,13 +2,14 @@ { public class WorkItemMongoDB { - public string? Id { get; set; } - public string? WorkAreaId { get; set; } + public string Id { get; set; } = string.Empty; + public string WorkAreaId { get; set; } = string.Empty; public ActivityMasterMongoDB? ActivityMaster { get; set; } public WorkCategoryMasterMongoDB? WorkCategoryMaster { get; set; } public string? ParentTaskId { get; set; } - public double PlannedWork { get; set; } - public double CompletedWork { get; set; } + public double PlannedWork { get; set; } = 0; + public double TodaysAssigned { get; set; } = 0; + public double CompletedWork { get; set; } = 0; public string? Description { get; set; } public DateTime TaskDate { get; set; } } diff --git a/Marco.Pms.Services/Controllers/RolesController.cs b/Marco.Pms.Services/Controllers/RolesController.cs index 4c75b3e..a67ecaf 100644 --- a/Marco.Pms.Services/Controllers/RolesController.cs +++ b/Marco.Pms.Services/Controllers/RolesController.cs @@ -292,6 +292,10 @@ namespace MarcoBMS.Services.Controllers _context.RolePermissionMappings.Add(item); modified = true; } + if (item.FeaturePermissionId == Guid.Parse("172fc9b6-755b-4f62-ab26-55c34a330614")) + { + await _cache.ClearAllProjectIdsByRoleId(id); + } } if (modified) await _context.SaveChangesAsync(); diff --git a/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs b/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs index 75b51b5..6ff9cfe 100644 --- a/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs +++ b/Marco.Pms.Services/Helpers/CacheUpdateHelper.cs @@ -28,7 +28,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while adding project to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while adding project {ProjectId} to Cache : {Error}", project.Id, ex.Message); } } public async Task UpdateProjectDetailsOnly(Project project) @@ -40,7 +40,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while updating project to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while updating project {ProjectId} to Cache: {Error}", project.Id, ex.Message); return false; } } @@ -53,15 +53,23 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while getting project to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while getting project {ProjectId} to Cache: {Error}", ex.Message); + return null; + } + } + public async Task?> GetProjectDetailsList(List projectIds) + { + try + { + var response = await _projectCache.GetProjectDetailsListFromCache(projectIds); + return response; + } + catch (Exception ex) + { + _logger.LogWarning("Error occured while getting list od project details from to Cache: {Error}", ex.Message); return null; } } - //public async Task?> GetProjectDetailsList(List projectIds) - //{ - // var response = await _projectCache.GetProjectDetailsListFromCache(projectIds); - // return response; - //} public async Task AddBuildngInfra(Guid projectId, Building? building = null, Floor? floor = null, WorkArea? workArea = null, Guid? buildingId = null) { try @@ -70,7 +78,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while adding project infra to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while adding project infra for project {ProjectId} to Cache: {Error}", projectId, ex.Message); } } public async Task UpdateBuildngInfra(Guid projectId, Building? building = null, Floor? floor = null, WorkArea? workArea = null, Guid? buildingId = null) @@ -85,7 +93,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while updating project infra to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while updating project infra for project {ProjectId} to Cache: {Error}", projectId, ex.Message); } } public async Task?> GetBuildingInfra(Guid projectId) @@ -97,7 +105,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while getting project infra Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while getting project infra for project {ProjectId} form Cache: {Error}", projectId, ex.Message); return null; } } @@ -124,7 +132,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while adding projectIds to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while adding projectIds for employee {EmployeeId} to Cache: {Error}", employeeId, ex.Message); return false; } } @@ -141,7 +149,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while getting projectIDs to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while getting projectIds for employee {EmployeeId} from Cache: {Error}", employeeId, ex.Message); return null; } } @@ -158,7 +166,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while getting permissionIds to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while getting permissionIds for employee {EmployeeId} from Cache: {Error}", employeeId, ex.Message); return null; } } @@ -173,10 +181,17 @@ namespace Marco.Pms.Services.Helpers _logger.LogWarning("Error occured while deleting projectIds from Cache for employee {EmployeeId}: {Error}", employeeId, ex.Message); } } - //public async Task ClearAllProjectIdsByRoleId(Guid roleId) - //{ - // await _employeeCache.ClearAllProjectIdsByRoleIdFromCache(roleId); - //} + public async Task ClearAllProjectIdsByRoleId(Guid roleId) + { + try + { + await _employeeCache.ClearAllProjectIdsByRoleIdFromCache(roleId); + } + catch (Exception ex) + { + _logger.LogWarning("Error occured while deleting projectIds from Cache for Application Role {RoleId}: {Error}", roleId, ex.Message); + } + } public async Task ClearAllPermissionIdsByEmployeeID(Guid employeeId) { try @@ -185,7 +200,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while deleting permissionIds from to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while deleting permissionIds from Cache for employee {EmployeeId}: {Error}", employeeId, ex.Message); } } public async Task ClearAllPermissionIdsByRoleId(Guid roleId) @@ -196,7 +211,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while deleting permissionIds from to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while deleting permissionIds from Cache for Application role {RoleId}: {Error}", roleId, ex.Message); } } public async Task RemoveRoleId(Guid employeeId, Guid roleId) @@ -207,7 +222,7 @@ namespace Marco.Pms.Services.Helpers } catch (Exception ex) { - _logger.LogWarning("Error occured while deleting Application roleIds from to Cache: {Error}", ex.Message); + _logger.LogWarning("Error occured while deleting Application role {RoleId} from Cache for employee {EmployeeId}: {Error}", roleId, employeeId, ex.Message); } } } diff --git a/Marco.Pms.Services/Helpers/ProjectsHelper.cs b/Marco.Pms.Services/Helpers/ProjectsHelper.cs index 3ccddba..85003ae 100644 --- a/Marco.Pms.Services/Helpers/ProjectsHelper.cs +++ b/Marco.Pms.Services/Helpers/ProjectsHelper.cs @@ -1,6 +1,7 @@ using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; +using Marco.Pms.Model.MongoDBModels; using Marco.Pms.Model.Projects; using Marco.Pms.Services.Helpers; using Microsoft.EntityFrameworkCore; @@ -59,7 +60,25 @@ namespace MarcoBMS.Services.Helpers if (projectIds != null) { - projects = await _context.Projects.Where(p => projectIds.Contains(p.Id)).ToListAsync(); + + List projectdetails = await _cache.GetProjectDetailsList(projectIds) ?? new List(); + projects = projectdetails.Select(p => new Project + { + Id = Guid.Parse(p.Id), + Name = p.Name, + ShortName = p.ShortName, + ProjectAddress = p.ProjectAddress, + ProjectStatusId = Guid.Parse(p.ProjectStatus?.Id ?? ""), + ContactPerson = p.ContactPerson, + StartDate = p.StartDate, + EndDate = p.EndDate, + TenantId = tenantId + }).ToList(); + + if (projects.Count != projectIds.Count) + { + projects = await _context.Projects.Where(p => projectIds.Contains(p.Id)).ToListAsync(); + } } else {