diff --git a/Marco.Pms.Services/Service/FirebaseService.cs b/Marco.Pms.Services/Service/FirebaseService.cs index 1caf5d2..afacc6a 100644 --- a/Marco.Pms.Services/Service/FirebaseService.cs +++ b/Marco.Pms.Services/Service/FirebaseService.cs @@ -333,14 +333,14 @@ namespace Marco.Pms.Services.Service }).FirstOrDefaultAsync(); }); - var teamMemberTask = Task.Run(async () => + var viewTaskRoleTask = Task.Run(async () => { await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.RolePermissionMappings .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) .Select(rp => rp.ApplicationRoleId).ToListAsync(); }); - var viewTaskRoleTask = Task.Run(async () => + var teamMemberTask = Task.Run(async () => { await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.TaskMembers @@ -486,9 +486,9 @@ namespace Marco.Pms.Services.Service var viewTaskRoleTask = Task.Run(async () => { await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); - return await dbContext.TaskMembers - .Where(tm => tm.TaskAllocationId == taskAllocationId && tm.TenantId == tenantId) - .Select(tm => tm.EmployeeId).ToListAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); }); var manageProjectsRoleTask = Task.Run(async () => @@ -585,14 +585,14 @@ namespace Marco.Pms.Services.Service }).FirstOrDefaultAsync(); }); - var teamMemberTask = Task.Run(async () => + var viewTaskRoleTask = Task.Run(async () => { await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.RolePermissionMappings .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) .Select(rp => rp.ApplicationRoleId).ToListAsync(); }); - var viewTaskRoleTask = Task.Run(async () => + var teamMemberTask = Task.Run(async () => { await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.TaskMembers @@ -669,6 +669,470 @@ namespace Marco.Pms.Services.Service } // Project Controller + public async Task SendModifyTaskMeaasgeAsync(List workItemIds, string name, bool IsExist, Guid tenantId) + { + + using var scope = _serviceScopeFactory.CreateScope(); + var _logger = scope.ServiceProvider.GetRequiredService(); + + try + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + + var workItems = await _context.WorkItems + .Include(wi => wi.ActivityMaster) + .Include(wi => wi.WorkArea) + .ThenInclude(wa => wa!.Floor) + .ThenInclude(f => f!.Building) + .Where(wi => workItemIds.Contains(wi.Id) && + wi.TenantId == tenantId && + wi.ActivityMaster != null && + wi.WorkArea != null && + wi.WorkArea.Floor != null && + wi.WorkArea.Floor.Building != null) + .ToListAsync(); + + if (!workItems.Any()) + { + return; + } + + var workItem = workItems.FirstOrDefault(); + + var projectId = workItem!.WorkArea!.Floor!.Building!.ProjectId; + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ProjectAllocations + .Include(pa => pa.Project) + .Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.Project != null) + .GroupBy(pa => pa.ProjectId) + .Select(g => new + { + ProjectName = g.Select(pa => pa.Project!.Name).FirstOrDefault(), + EmployeeIds = g.Select(pa => pa.EmployeeId).Distinct().ToList() + }).FirstOrDefaultAsync(); + }); + + var viewTaskRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + var viewProjectInfraRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewProjectInfra) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + var manageProjectsRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ManageProject) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + await Task.WhenAll(projectTask, viewTaskRoleTask, manageProjectsRoleTask, viewProjectInfraRoleTask); + + var viewTaskRoleIds = viewTaskRoleTask.Result; + var manageProjectsRoleIds = manageProjectsRoleTask.Result; + var viewProjectInfraRoleIds = viewProjectInfraRoleTask.Result; + var project = projectTask.Result; + + var activityName = workItem.ActivityMaster!.ActivityName; + + var buildingName = workItem.WorkArea.Floor.Building.Name; + var FloorName = workItem.WorkArea.Floor.FloorName; + var AreaName = workItem.WorkArea.AreaName; + + var location = $"{buildingName} > {FloorName} > {AreaName}"; + + var buildingId = workItem.WorkArea.Floor.Building.Id; + var floorId = workItem.WorkArea.Floor.Id; + var areaId = workItem.WorkArea.Id; + + List projectAssignedEmployeeIds = project?.EmployeeIds ?? new List(); + + var employeeIds = await _context.EmployeeRoleMappings + .Where(er => + (projectAssignedEmployeeIds.Contains(er.EmployeeId) || manageProjectsRoleIds.Contains(er.RoleId)) && + (viewTaskRoleIds.Contains(er.RoleId) || viewProjectInfraRoleIds.Contains(er.RoleId))) + .Select(er => er.EmployeeId) + .ToListAsync(); + + Notification notificationFirebase; + if (IsExist) + { + notificationFirebase = new Notification + { + Title = $"New Task Updated - {project?.ProjectName}", + Body = $"{name} updated tasks {activityName} at {location}." + }; + } + else + { + notificationFirebase = new Notification + { + Title = $"New Task Created - {project?.ProjectName}", + Body = $"{name} created tasks {activityName} at {location}." + }; + } + + var data = new Dictionary() + { + { "Keyword", "Task_Modified" }, + { "ProjectId", projectId.ToString() }, + { "BuildingId", buildingId.ToString() }, + { "FloorId", floorId.ToString() }, + { "AreaId", areaId.ToString() }, + }; + + + // List of device registration tokens to send the message to + var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => employeeIds.Contains(ft.EmployeeId)).Select(ft => ft.FcmToken).ToListAsync(); + + await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notificationFirebase, data); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while get data for sending notification"); + } + } + public async Task SendModifyWorkAreaMeaasgeAsync(Guid workAreaId, string name, bool IsExist, Guid tenantId) + { + + using var scope = _serviceScopeFactory.CreateScope(); + var _logger = scope.ServiceProvider.GetRequiredService(); + + try + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + + var workArea = await _context.WorkAreas + .Include(wa => wa.Floor) + .ThenInclude(f => f!.Building) + .FirstOrDefaultAsync(wa => wa.Id == workAreaId && + wa.TenantId == tenantId && + wa.Floor != null && + wa.Floor.Building != null); + + if (workArea == null) + { + return; + } + + var projectId = workArea.Floor!.Building!.ProjectId; + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ProjectAllocations + .Include(pa => pa.Project) + .Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.Project != null) + .GroupBy(pa => pa.ProjectId) + .Select(g => new + { + ProjectName = g.Select(pa => pa.Project!.Name).FirstOrDefault(), + EmployeeIds = g.Select(pa => pa.EmployeeId).Distinct().ToList() + }).FirstOrDefaultAsync(); + }); + + var viewProjectInfraRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewProjectInfra) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + var manageProjectsRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ManageProject) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + await Task.WhenAll(projectTask, manageProjectsRoleTask, viewProjectInfraRoleTask); + + var manageProjectsRoleIds = manageProjectsRoleTask.Result; + var viewProjectInfraRoleIds = viewProjectInfraRoleTask.Result; + var project = projectTask.Result; + + var buildingName = workArea.Floor.Building.Name; + var FloorName = workArea.Floor.FloorName; + + var location = $"{buildingName} > {FloorName}"; + + var buildingId = workArea.Floor.Building.Id; + var floorId = workArea.Floor.Id; + var areaName = workArea.AreaName; + + List projectAssignedEmployeeIds = project?.EmployeeIds ?? new List(); + + var employeeIds = await _context.EmployeeRoleMappings + .Where(er => + (projectAssignedEmployeeIds.Contains(er.EmployeeId) || manageProjectsRoleIds.Contains(er.RoleId)) && viewProjectInfraRoleIds.Contains(er.RoleId)) + .Select(er => er.EmployeeId) + .ToListAsync(); + + Notification notificationFirebase; + if (IsExist) + { + notificationFirebase = new Notification + { + Title = $"WorkArea Updated - {project?.ProjectName}", + Body = $"{name} updated WorkArea \"{areaName}\" at {location}." + }; + } + else + { + notificationFirebase = new Notification + { + Title = $"New WorkArea Created - {project?.ProjectName}", + Body = $"{name} created WorkArea \"{areaName}\" at {location}." + }; + } + + var data = new Dictionary() + { + { "Keyword", "Task_Modified" }, + { "ProjectId", projectId.ToString() }, + { "BuildingId", buildingId.ToString() }, + { "FloorId", floorId.ToString() } + }; + + + // List of device registration tokens to send the message to + var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => employeeIds.Contains(ft.EmployeeId)).Select(ft => ft.FcmToken).ToListAsync(); + + await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notificationFirebase, data); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while get data for sending notification"); + } + } + public async Task SendModifyFloorMeaasgeAsync(Guid floorId, string name, bool IsExist, Guid tenantId) + { + + using var scope = _serviceScopeFactory.CreateScope(); + var _logger = scope.ServiceProvider.GetRequiredService(); + + try + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + + var floor = await _context.Floor + .Include(f => f.Building) + .FirstOrDefaultAsync(f => f.Id == floorId && + f.TenantId == tenantId && + f.Building != null); + + if (floor == null) + { + return; + } + + var projectId = floor.Building!.ProjectId; + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ProjectAllocations + .Include(pa => pa.Project) + .Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.Project != null) + .GroupBy(pa => pa.ProjectId) + .Select(g => new + { + ProjectName = g.Select(pa => pa.Project!.Name).FirstOrDefault(), + EmployeeIds = g.Select(pa => pa.EmployeeId).Distinct().ToList() + }).FirstOrDefaultAsync(); + }); + + var viewProjectInfraRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewProjectInfra) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + var manageProjectsRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ManageProject) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + await Task.WhenAll(projectTask, manageProjectsRoleTask, viewProjectInfraRoleTask); + + var manageProjectsRoleIds = manageProjectsRoleTask.Result; + var viewProjectInfraRoleIds = viewProjectInfraRoleTask.Result; + var project = projectTask.Result; + + var buildingName = floor.Building.Name; + var floorName = floor.FloorName; + + var buildingId = floor.Building.Id; + + List projectAssignedEmployeeIds = project?.EmployeeIds ?? new List(); + + var employeeIds = await _context.EmployeeRoleMappings + .Where(er => + (projectAssignedEmployeeIds.Contains(er.EmployeeId) || manageProjectsRoleIds.Contains(er.RoleId)) && viewProjectInfraRoleIds.Contains(er.RoleId)) + .Select(er => er.EmployeeId) + .ToListAsync(); + + Notification notificationFirebase; + if (IsExist) + { + notificationFirebase = new Notification + { + Title = $"Floor Updated - {project?.ProjectName}", + Body = $"{name} updated Floor \"{floorName}\" at {buildingName}." + }; + } + else + { + notificationFirebase = new Notification + { + Title = $"New Floor Created - {project?.ProjectName}", + Body = $"{name} created Floor \"{floorName}\" at {buildingName}." + }; + } + + var data = new Dictionary() + { + { "Keyword", "Task_Modified" }, + { "ProjectId", projectId.ToString() }, + { "BuildingId", buildingId.ToString() } + }; + + + // List of device registration tokens to send the message to + var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => employeeIds.Contains(ft.EmployeeId)).Select(ft => ft.FcmToken).ToListAsync(); + + await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notificationFirebase, data); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while get data for sending notification"); + } + } + public async Task SendModifyBuildingMeaasgeAsync(Guid buildingId, string name, bool IsExist, Guid tenantId) + { + + using var scope = _serviceScopeFactory.CreateScope(); + var _logger = scope.ServiceProvider.GetRequiredService(); + + try + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + + var building = await _context.Buildings + .FirstOrDefaultAsync(b => b.Id == buildingId && + b.TenantId == tenantId); + + if (building == null) + { + return; + } + + var projectId = building.ProjectId; + + var projectTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ProjectAllocations + .Include(pa => pa.Project) + .Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.Project != null) + .GroupBy(pa => pa.ProjectId) + .Select(g => new + { + ProjectName = g.Select(pa => pa.Project!.Name).FirstOrDefault(), + EmployeeIds = g.Select(pa => pa.EmployeeId).Distinct().ToList() + }).FirstOrDefaultAsync(); + }); + + var viewProjectInfraRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewProjectInfra) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + var manageProjectsRoleTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.RolePermissionMappings + .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ManageProject) + .Select(rp => rp.ApplicationRoleId).ToListAsync(); + }); + + await Task.WhenAll(projectTask, manageProjectsRoleTask, viewProjectInfraRoleTask); + + var manageProjectsRoleIds = manageProjectsRoleTask.Result; + var viewProjectInfraRoleIds = viewProjectInfraRoleTask.Result; + var project = projectTask.Result; + + List projectAssignedEmployeeIds = project?.EmployeeIds ?? new List(); + + var employeeIds = await _context.EmployeeRoleMappings + .Where(er => + (projectAssignedEmployeeIds.Contains(er.EmployeeId) || manageProjectsRoleIds.Contains(er.RoleId)) && viewProjectInfraRoleIds.Contains(er.RoleId)) + .Select(er => er.EmployeeId) + .ToListAsync(); + + var buildingName = building.Name; + + Notification notificationFirebase; + if (IsExist) + { + notificationFirebase = new Notification + { + Title = $"Building Updated - {project?.ProjectName}", + Body = $"{name} updated building \"{buildingName}\" in {project?.ProjectName}." + }; + } + else + { + notificationFirebase = new Notification + { + Title = $"New Building Created - {project?.ProjectName}", + Body = $"\"{{name}} created a new building \"{buildingName}\" in {project?.ProjectName}." + }; + } + + var data = new Dictionary() + { + { "Keyword", "Building_Modified" }, + { "ProjectId", projectId.ToString() } + }; + + + // List of device registration tokens to send the message to + var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => employeeIds.Contains(ft.EmployeeId)).Select(ft => ft.FcmToken).ToListAsync(); + + await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notificationFirebase, data); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while get data for sending notification"); + } + } + + + + #region =================================================================== Helper Functions =================================================================== public async Task SendMessageToMultipleDevicesWithDataAsync(List registrationTokens, Notification notificationFirebase, Dictionary data) { @@ -816,5 +1280,7 @@ namespace Marco.Pms.Services.Service } } + + #endregion } } diff --git a/Marco.Pms.Services/Service/ProjectServices.cs b/Marco.Pms.Services/Service/ProjectServices.cs index 6cb7e68..41e3726 100644 --- a/Marco.Pms.Services/Service/ProjectServices.cs +++ b/Marco.Pms.Services/Service/ProjectServices.cs @@ -22,20 +22,20 @@ namespace Marco.Pms.Services.Service public class ProjectServices : IProjectServices { private readonly IDbContextFactory _dbContextFactory; + private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate private readonly ILoggingService _logger; private readonly PermissionServices _permission; private readonly CacheUpdateHelper _cache; private readonly IMapper _mapper; - private readonly GeneralHelper _generalHelper; public ProjectServices( IDbContextFactory dbContextFactory, + IServiceScopeFactory serviceScopeFactory, ApplicationDbContext context, ILoggingService logger, PermissionServices permission, CacheUpdateHelper cache, - IMapper mapper, - GeneralHelper generalHelper) + IMapper mapper) { _dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory)); _context = context ?? throw new ArgumentNullException(nameof(context)); @@ -43,7 +43,7 @@ namespace Marco.Pms.Services.Service _permission = permission ?? throw new ArgumentNullException(nameof(permission)); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); - _generalHelper = generalHelper ?? throw new ArgumentNullException(nameof(generalHelper)); + _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); } #region =================================================================== Project Get APIs =================================================================== @@ -974,6 +974,9 @@ namespace Marco.Pms.Services.Service { _logger.LogInfo("GetInfraDetails called for ProjectId: {ProjectId}", projectId); + using var scope = _serviceScopeFactory.CreateScope(); + var _generalHelper = scope.ServiceProvider.GetRequiredService(); + try { // --- Step 1: Run independent permission checks in PARALLEL --- @@ -1030,6 +1033,9 @@ namespace Marco.Pms.Services.Service { _logger.LogInfo("GetWorkItems called for WorkAreaId: {WorkAreaId} by User: {UserId}", workAreaId, loggedInEmployee.Id); + using var scope = _serviceScopeFactory.CreateScope(); + var _generalHelper = scope.ServiceProvider.GetRequiredService(); + try { // --- Step 1: Cache-First Strategy --- @@ -1219,15 +1225,15 @@ namespace Marco.Pms.Services.Service { if (item.Building != null) { - ProcessBuilding(item.Building, tenantId, responseData, messages, projectIds, cacheUpdateTasks); + ProcessBuilding(item.Building, tenantId, responseData, messages, projectIds, cacheUpdateTasks, loggedInEmployee); } if (item.Floor != null) { - ProcessFloor(item.Floor, tenantId, responseData, messages, projectIds, cacheUpdateTasks, buildingsDict); + ProcessFloor(item.Floor, tenantId, responseData, messages, projectIds, cacheUpdateTasks, buildingsDict, loggedInEmployee); } if (item.WorkArea != null) { - ProcessWorkArea(item.WorkArea, tenantId, responseData, messages, projectIds, cacheUpdateTasks, floorsDict); + ProcessWorkArea(item.WorkArea, tenantId, responseData, messages, projectIds, cacheUpdateTasks, floorsDict, loggedInEmployee); } } @@ -1268,6 +1274,9 @@ namespace Marco.Pms.Services.Service { _logger.LogInfo("CreateProjectTask called with {Count} items by user {UserId}", workItemDtos?.Count ?? 0, loggedInEmployee.Id); + using var scope = _serviceScopeFactory.CreateScope(); + var _firebase = scope.ServiceProvider.GetRequiredService(); + // --- Step 1: Input Validation --- if (workItemDtos == null || !workItemDtos.Any()) { @@ -1379,6 +1388,29 @@ namespace Marco.Pms.Services.Service WorkItem = wi }).ToList(); + _ = Task.Run(async () => + { + // --- Push Notification Section --- + // This section attempts to send a test push notification to the user's device. + // It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens. + + var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}"; + + List workItemIds = new List(); + bool IsExist = false; + + if (workItemsToCreate.Any()) + workItemIds = workItemsToCreate.Select(wi => wi.Id).ToList(); + if (workItemsToModify.Any()) + { + workItemIds = workItemsToModify.Select(wi => wi.Id).ToList(); + IsExist = true; + } + + if (workItemIds.Any()) + await _firebase.SendModifyTaskMeaasgeAsync(workItemIds, name, IsExist, tenantId); + + }); return ApiResponse>.SuccessResponse(responseList, message, 200); } @@ -1448,9 +1480,9 @@ namespace Marco.Pms.Services.Service // 6. Perform cache operations concurrently. var cacheTasks = new List - { - _cache.DeleteWorkItemByIdAsync(task.Id) - }; + { + _cache.DeleteWorkItemByIdAsync(task.Id) + }; if (building?.ProjectId != null) { @@ -1814,8 +1846,11 @@ namespace Marco.Pms.Services.Service } } - private void ProcessBuilding(BuildingDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks) + private void ProcessBuilding(BuildingDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks, Employee loggedInEmployee) { + using var scope = _serviceScopeFactory.CreateScope(); + var _firebase = scope.ServiceProvider.GetRequiredService(); + Building building = _mapper.Map(dto); building.TenantId = tenantId; @@ -1835,10 +1870,24 @@ namespace Marco.Pms.Services.Service responseData.building = building; projectIds.Add(building.ProjectId); + _ = Task.Run(async () => + { + // --- Push Notification Section --- + // This section attempts to send a test push notification to the user's device. + // It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens. + + var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}"; + + await _firebase.SendModifyBuildingMeaasgeAsync(building.Id, name, !isNew, tenantId); + + }); } - private void ProcessFloor(FloorDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks, IDictionary buildings) + private void ProcessFloor(FloorDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks, IDictionary buildings, Employee loggedInEmployee) { + using var scope = _serviceScopeFactory.CreateScope(); + var _firebase = scope.ServiceProvider.GetRequiredService(); + Floor floor = _mapper.Map(dto); floor.TenantId = tenantId; @@ -1861,10 +1910,25 @@ namespace Marco.Pms.Services.Service responseData.floor = floor; if (parentBuilding != null) projectIds.Add(parentBuilding.ProjectId); + + _ = Task.Run(async () => + { + // --- Push Notification Section --- + // This section attempts to send a test push notification to the user's device. + // It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens. + + var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}"; + + await _firebase.SendModifyFloorMeaasgeAsync(floor.Id, name, !isNew, tenantId); + + }); } - private void ProcessWorkArea(WorkAreaDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks, IDictionary floors) + private void ProcessWorkArea(WorkAreaDto dto, Guid tenantId, InfraVM responseData, List messages, ISet projectIds, List cacheTasks, IDictionary floors, Employee loggedInEmployee) { + using var scope = _serviceScopeFactory.CreateScope(); + var _firebase = scope.ServiceProvider.GetRequiredService(); + WorkArea workArea = _mapper.Map(dto); workArea.TenantId = tenantId; @@ -1888,6 +1952,18 @@ namespace Marco.Pms.Services.Service responseData.workArea = workArea; if (parentBuilding != null) projectIds.Add(parentBuilding.ProjectId); + + _ = Task.Run(async () => + { + // --- Push Notification Section --- + // This section attempts to send a test push notification to the user's device. + // It's designed to fail gracefully and handle invalid Firebase Cloud Messaging (FCM) tokens. + + var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}"; + + await _firebase.SendModifyWorkAreaMeaasgeAsync(workArea.Id, name, !isNew, tenantId); + + }); } #endregion diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IFirebaseService.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IFirebaseService.cs index e8175f3..035005c 100644 --- a/Marco.Pms.Services/Service/ServiceInterfaces/IFirebaseService.cs +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IFirebaseService.cs @@ -10,5 +10,9 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces Task SendReportTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId); Task SendTaskCommentMessageAsync(Guid taskAllocationId, string name, Guid tenantId); Task SendApproveTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId); + Task SendModifyTaskMeaasgeAsync(List workItemIds, string name, bool IsExist, Guid tenantId); + Task SendModifyWorkAreaMeaasgeAsync(Guid workAreaId, string name, bool IsExist, Guid tenantId); + Task SendModifyFloorMeaasgeAsync(Guid floorId, string name, bool IsExist, Guid tenantId); + Task SendModifyBuildingMeaasgeAsync(Guid buildingId, string name, bool IsExist, Guid tenantId); } }