Firebase_Implementation #135

Merged
ashutosh.nehete merged 62 commits from Firebase_Implementation into main 2025-09-20 12:11:54 +00:00
3 changed files with 566 additions and 20 deletions
Showing only changes of commit 38450dce70 - Show all commits

View File

@ -333,14 +333,14 @@ namespace Marco.Pms.Services.Service
}).FirstOrDefaultAsync(); }).FirstOrDefaultAsync();
}); });
var teamMemberTask = Task.Run(async () => var viewTaskRoleTask = Task.Run(async () =>
{ {
await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.RolePermissionMappings return await dbContext.RolePermissionMappings
.Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask)
.Select(rp => rp.ApplicationRoleId).ToListAsync(); .Select(rp => rp.ApplicationRoleId).ToListAsync();
}); });
var viewTaskRoleTask = Task.Run(async () => var teamMemberTask = Task.Run(async () =>
{ {
await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.TaskMembers return await dbContext.TaskMembers
@ -486,9 +486,9 @@ namespace Marco.Pms.Services.Service
var viewTaskRoleTask = Task.Run(async () => var viewTaskRoleTask = Task.Run(async () =>
{ {
await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.TaskMembers return await dbContext.RolePermissionMappings
.Where(tm => tm.TaskAllocationId == taskAllocationId && tm.TenantId == tenantId) .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask)
.Select(tm => tm.EmployeeId).ToListAsync(); .Select(rp => rp.ApplicationRoleId).ToListAsync();
}); });
var manageProjectsRoleTask = Task.Run(async () => var manageProjectsRoleTask = Task.Run(async () =>
@ -585,14 +585,14 @@ namespace Marco.Pms.Services.Service
}).FirstOrDefaultAsync(); }).FirstOrDefaultAsync();
}); });
var teamMemberTask = Task.Run(async () => var viewTaskRoleTask = Task.Run(async () =>
{ {
await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.RolePermissionMappings return await dbContext.RolePermissionMappings
.Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask) .Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewTask)
.Select(rp => rp.ApplicationRoleId).ToListAsync(); .Select(rp => rp.ApplicationRoleId).ToListAsync();
}); });
var viewTaskRoleTask = Task.Run(async () => var teamMemberTask = Task.Run(async () =>
{ {
await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.TaskMembers return await dbContext.TaskMembers
@ -669,6 +669,470 @@ namespace Marco.Pms.Services.Service
} }
// Project Controller // Project Controller
public async Task SendModifyTaskMeaasgeAsync(List<Guid> workItemIds, string name, bool IsExist, Guid tenantId)
{
using var scope = _serviceScopeFactory.CreateScope();
var _logger = scope.ServiceProvider.GetRequiredService<ILoggingService>();
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<Guid> projectAssignedEmployeeIds = project?.EmployeeIds ?? new List<Guid>();
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<string, string>()
{
{ "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<ILoggingService>();
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<Guid> projectAssignedEmployeeIds = project?.EmployeeIds ?? new List<Guid>();
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<string, string>()
{
{ "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<ILoggingService>();
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<Guid> projectAssignedEmployeeIds = project?.EmployeeIds ?? new List<Guid>();
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<string, string>()
{
{ "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<ILoggingService>();
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<Guid> projectAssignedEmployeeIds = project?.EmployeeIds ?? new List<Guid>();
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<string, string>()
{
{ "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<string> registrationTokens, Notification notificationFirebase, Dictionary<string, string> data) public async Task SendMessageToMultipleDevicesWithDataAsync(List<string> registrationTokens, Notification notificationFirebase, Dictionary<string, string> data)
{ {
@ -816,5 +1280,7 @@ namespace Marco.Pms.Services.Service
} }
} }
#endregion
} }
} }

View File

@ -22,20 +22,20 @@ namespace Marco.Pms.Services.Service
public class ProjectServices : IProjectServices public class ProjectServices : IProjectServices
{ {
private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory; private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private readonly PermissionServices _permission; private readonly PermissionServices _permission;
private readonly CacheUpdateHelper _cache; private readonly CacheUpdateHelper _cache;
private readonly IMapper _mapper; private readonly IMapper _mapper;
private readonly GeneralHelper _generalHelper;
public ProjectServices( public ProjectServices(
IDbContextFactory<ApplicationDbContext> dbContextFactory, IDbContextFactory<ApplicationDbContext> dbContextFactory,
IServiceScopeFactory serviceScopeFactory,
ApplicationDbContext context, ApplicationDbContext context,
ILoggingService logger, ILoggingService logger,
PermissionServices permission, PermissionServices permission,
CacheUpdateHelper cache, CacheUpdateHelper cache,
IMapper mapper, IMapper mapper)
GeneralHelper generalHelper)
{ {
_dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory)); _dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory));
_context = context ?? throw new ArgumentNullException(nameof(context)); _context = context ?? throw new ArgumentNullException(nameof(context));
@ -43,7 +43,7 @@ namespace Marco.Pms.Services.Service
_permission = permission ?? throw new ArgumentNullException(nameof(permission)); _permission = permission ?? throw new ArgumentNullException(nameof(permission));
_cache = cache ?? throw new ArgumentNullException(nameof(cache)); _cache = cache ?? throw new ArgumentNullException(nameof(cache));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); _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 =================================================================== #region =================================================================== Project Get APIs ===================================================================
@ -974,6 +974,9 @@ namespace Marco.Pms.Services.Service
{ {
_logger.LogInfo("GetInfraDetails called for ProjectId: {ProjectId}", projectId); _logger.LogInfo("GetInfraDetails called for ProjectId: {ProjectId}", projectId);
using var scope = _serviceScopeFactory.CreateScope();
var _generalHelper = scope.ServiceProvider.GetRequiredService<GeneralHelper>();
try try
{ {
// --- Step 1: Run independent permission checks in PARALLEL --- // --- 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); _logger.LogInfo("GetWorkItems called for WorkAreaId: {WorkAreaId} by User: {UserId}", workAreaId, loggedInEmployee.Id);
using var scope = _serviceScopeFactory.CreateScope();
var _generalHelper = scope.ServiceProvider.GetRequiredService<GeneralHelper>();
try try
{ {
// --- Step 1: Cache-First Strategy --- // --- Step 1: Cache-First Strategy ---
@ -1219,15 +1225,15 @@ namespace Marco.Pms.Services.Service
{ {
if (item.Building != null) 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) 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) 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); _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<IFirebaseService>();
// --- Step 1: Input Validation --- // --- Step 1: Input Validation ---
if (workItemDtos == null || !workItemDtos.Any()) if (workItemDtos == null || !workItemDtos.Any())
{ {
@ -1379,6 +1388,29 @@ namespace Marco.Pms.Services.Service
WorkItem = wi WorkItem = wi
}).ToList(); }).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<Guid> workItemIds = new List<Guid>();
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<List<WorkItemVM>>.SuccessResponse(responseList, message, 200); return ApiResponse<List<WorkItemVM>>.SuccessResponse(responseList, message, 200);
} }
@ -1448,9 +1480,9 @@ namespace Marco.Pms.Services.Service
// 6. Perform cache operations concurrently. // 6. Perform cache operations concurrently.
var cacheTasks = new List<Task> var cacheTasks = new List<Task>
{ {
_cache.DeleteWorkItemByIdAsync(task.Id) _cache.DeleteWorkItemByIdAsync(task.Id)
}; };
if (building?.ProjectId != null) if (building?.ProjectId != null)
{ {
@ -1814,8 +1846,11 @@ namespace Marco.Pms.Services.Service
} }
} }
private void ProcessBuilding(BuildingDto dto, Guid tenantId, InfraVM responseData, List<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks) private void ProcessBuilding(BuildingDto dto, Guid tenantId, InfraVM responseData, List<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks, Employee loggedInEmployee)
{ {
using var scope = _serviceScopeFactory.CreateScope();
var _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
Building building = _mapper.Map<Building>(dto); Building building = _mapper.Map<Building>(dto);
building.TenantId = tenantId; building.TenantId = tenantId;
@ -1835,10 +1870,24 @@ namespace Marco.Pms.Services.Service
responseData.building = building; responseData.building = building;
projectIds.Add(building.ProjectId); 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<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks, IDictionary<Guid, Building> buildings) private void ProcessFloor(FloorDto dto, Guid tenantId, InfraVM responseData, List<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks, IDictionary<Guid, Building> buildings, Employee loggedInEmployee)
{ {
using var scope = _serviceScopeFactory.CreateScope();
var _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
Floor floor = _mapper.Map<Floor>(dto); Floor floor = _mapper.Map<Floor>(dto);
floor.TenantId = tenantId; floor.TenantId = tenantId;
@ -1861,10 +1910,25 @@ namespace Marco.Pms.Services.Service
responseData.floor = floor; responseData.floor = floor;
if (parentBuilding != null) projectIds.Add(parentBuilding.ProjectId); 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<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks, IDictionary<Guid, Floor> floors) private void ProcessWorkArea(WorkAreaDto dto, Guid tenantId, InfraVM responseData, List<string> messages, ISet<Guid> projectIds, List<Task> cacheTasks, IDictionary<Guid, Floor> floors, Employee loggedInEmployee)
{ {
using var scope = _serviceScopeFactory.CreateScope();
var _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
WorkArea workArea = _mapper.Map<WorkArea>(dto); WorkArea workArea = _mapper.Map<WorkArea>(dto);
workArea.TenantId = tenantId; workArea.TenantId = tenantId;
@ -1888,6 +1952,18 @@ namespace Marco.Pms.Services.Service
responseData.workArea = workArea; responseData.workArea = workArea;
if (parentBuilding != null) projectIds.Add(parentBuilding.ProjectId); 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 #endregion

View File

@ -10,5 +10,9 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task SendReportTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId); Task SendReportTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId);
Task SendTaskCommentMessageAsync(Guid taskAllocationId, string name, Guid tenantId); Task SendTaskCommentMessageAsync(Guid taskAllocationId, string name, Guid tenantId);
Task SendApproveTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId); Task SendApproveTaskMessageAsync(Guid taskAllocationId, string name, Guid tenantId);
Task SendModifyTaskMeaasgeAsync(List<Guid> 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);
} }
} }