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 212 additions and 2 deletions
Showing only changes of commit 87ebee8005 - Show all commits

View File

@ -1,4 +1,5 @@
using AutoMapper;
using FirebaseAdmin.Messaging;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Helpers.Utility;
using Marco.Pms.Model.DocumentManager;
@ -10,6 +11,7 @@ using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.DocumentManager;
using Marco.Pms.Services.Service;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization;
@ -841,6 +843,38 @@ namespace Marco.Pms.Services.Controllers
response.ParentAttachmentId = versionMapping.ParentAttachmentId;
response.Version = versionMapping.Version;
_ = 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 _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}";
if (EmployeeEntity == entityType && model.EntityId != loggedInEmployee.Id)
{
var notification = new Notification
{
Title = $"Document added to Employee.",
Body = $"Document added to your profile of type \"{documentType.Name}\" by {name}"
};
await _firebase.SendEmployeeDocumentMessageAsync(model.EntityId, notification, tenantId);
}
if (ProjectEntity == entityType)
{
var notification = new Notification
{
Title = $"Document added to Project.",
Body = $"Document added to your Project of type \"{documentType.Name}\" by {name}"
};
await _firebase.SendProjectDocumentMessageAsync(model.EntityId, notification, tenantId);
}
});
return Ok(ApiResponse<object>.SuccessResponse(response, "Document added successfully", 200));
}
catch (Exception ex)
@ -932,6 +966,40 @@ namespace Marco.Pms.Services.Controllers
}
_logger.LogInfo("Document verified successfully. DocumentId: {DocumentId}, VerifiedBy: {EmployeeId}", documentAttachment.Id, loggedInEmployee.Id);
_ = 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 _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}";
var entityType = documentAttachment.DocumentType?.DocumentCategory?.EntityTypeId;
var documentType = documentAttachment.DocumentType;
if (EmployeeEntity == entityType && documentAttachment.EntityId != loggedInEmployee.Id)
{
var notification = new Notification
{
Title = $"Your Document is Verified.",
Body = $"Your Document of type \"{documentType?.Name}\" is Verified by {name}"
};
await _firebase.SendEmployeeDocumentMessageAsync(documentAttachment.EntityId, notification, tenantId);
}
if (ProjectEntity == entityType)
{
var notification = new Notification
{
Title = $"Document for your project is verified",
Body = $"Document for your Project of type \"{documentType?.Name}\" is Verified by {name}"
};
await _firebase.SendProjectDocumentMessageAsync(documentAttachment.EntityId, notification, tenantId);
}
});
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Document is verified successfully", 200));
}
catch (Exception ex)
@ -1176,7 +1244,7 @@ namespace Marco.Pms.Services.Controllers
oldAttachment.DocumentId = model.DocumentId;
oldAttachment.Description = model.Description;
oldAttachment.DocumentDataId = document.Id;
if (oldAttachment.IsVerified == true)
if (oldAttachment.IsVerified != null)
{
oldAttachment.IsVerified = null;
_logger.LogInfo("Reset verification flag for AttachmentId: {AttachmentId}", oldAttachment.Id);
@ -1196,7 +1264,7 @@ namespace Marco.Pms.Services.Controllers
oldAttachment.Name = model.Name;
oldAttachment.DocumentId = model.DocumentId;
oldAttachment.Description = model.Description;
if (oldAttachment.IsVerified == true)
if (oldAttachment.IsVerified != null)
{
oldAttachment.IsVerified = null;
_logger.LogInfo("Reset verification flag for AttachmentId: {AttachmentId}", oldAttachment.Id);
@ -1288,6 +1356,38 @@ namespace Marco.Pms.Services.Controllers
response.Version = newVersionMapping.Version;
_logger.LogInfo("API completed successfully for AttachmentId: {AttachmentId}", newAttachment.Id);
_ = 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 _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}";
if (EmployeeEntity == entityType && newAttachment.EntityId != loggedInEmployee.Id)
{
var notification = new Notification
{
Title = $"Your Document is updated.",
Body = $"Your Document of type \"{documentType?.Name}\" is updated by {name}"
};
await _firebase.SendEmployeeDocumentMessageAsync(newAttachment.EntityId, notification, tenantId);
}
if (ProjectEntity == entityType)
{
var notification = new Notification
{
Title = "Your Project Document is updated.",
Body = $"Your Project Document of type \"{documentType?.Name}\" is updated by {name}"
};
await _firebase.SendProjectDocumentMessageAsync(newAttachment.EntityId, notification, tenantId);
}
});
return Ok(ApiResponse<object>.SuccessResponse(response, "Document Updated successfully", 200));
}
catch (Exception ex)
@ -1371,6 +1471,41 @@ namespace Marco.Pms.Services.Controllers
// Log the successful completion of the operation
_logger.LogInfo("DocumentAttachment ID: {DocumentId} has been {Message} by employee ID: {EmployeeId}", id, message, loggedInEmployee.Id);
_ = 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 _firebase = scope.ServiceProvider.GetRequiredService<IFirebaseService>();
var entityType = documentAttachment.DocumentType?.DocumentCategory?.EntityTypeId;
var documentType = documentAttachment.DocumentType;
var name = $"{loggedInEmployee.FirstName} {loggedInEmployee.LastName}";
if (EmployeeEntity == entityType && documentAttachment.EntityId != loggedInEmployee.Id)
{
var notification = new Notification
{
Title = $"Your Document is {message}.",
Body = $"Your Document of type \"{documentType?.Name}\" is {message} by {name}"
};
await _firebase.SendEmployeeDocumentMessageAsync(documentAttachment.EntityId, notification, tenantId);
}
if (ProjectEntity == entityType)
{
var notification = new Notification
{
Title = "Your Project Document is {message}.",
Body = $"Your Project Document of type \"{documentType?.Name}\" is {message} by {name}"
};
await _firebase.SendProjectDocumentMessageAsync(documentAttachment.EntityId, notification, tenantId);
}
});
// Return success response
return Ok(ApiResponse<object>.SuccessResponse(new { }, $"Document attachment is {message}", 200));
}

View File

@ -1769,6 +1769,78 @@ namespace Marco.Pms.Services.Service
await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notification, data);
}
//Document Controller
public async Task SendEmployeeDocumentMessageAsync(Guid employeeId, Notification notification, Guid tenantId)
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
using var scope = _serviceScopeFactory.CreateScope();
var data = new Dictionary<string, string>()
{
{ "Keyword", "Employee_Document_Modefied" }
};
var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => ft.EmployeeId == employeeId && ft.ExpiredAt >= DateTime.UtcNow).Select(ft => ft.FcmToken).ToListAsync();
await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notification, data);
}
public async Task SendProjectDocumentMessageAsync(Guid projectId, Notification notification, Guid tenantId)
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
using var scope = _serviceScopeFactory.CreateScope();
var assignedEmployeeIdsTask = Task.Run(async () =>
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
return await _context.ProjectAllocations.Where(pa => projectId == pa.ProjectId).Select(pa => pa.EmployeeId).ToListAsync();
});
var manageProjectEmployeeIdsTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
var roleIds = await dbContext.RolePermissionMappings
.Where(rp => rp.FeaturePermissionId == PermissionsMaster.ManageProject)
.Select(rp => rp.ApplicationRoleId).ToListAsync();
var employeeIds = await dbContext.EmployeeRoleMappings
.Where(er =>
roleIds.Contains(er.RoleId))
.Select(er => er.EmployeeId)
.ToListAsync();
return employeeIds;
});
var viewDocumentEmployeeIdsTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
var roleIds = await dbContext.RolePermissionMappings
.Where(rp => rp.FeaturePermissionId == PermissionsMaster.ViewDocument)
.Select(rp => rp.ApplicationRoleId).ToListAsync();
var employeeIds = await dbContext.EmployeeRoleMappings
.Where(er =>
roleIds.Contains(er.RoleId))
.Select(er => er.EmployeeId)
.ToListAsync();
return employeeIds;
});
await Task.WhenAll(assignedEmployeeIdsTask, manageProjectEmployeeIdsTask, viewDocumentEmployeeIdsTask);
var assignedEmployeeIds = assignedEmployeeIdsTask.Result;
var manageProjectEmployeeIds = manageProjectEmployeeIdsTask.Result;
var viewDocumentEmployeeIds = viewDocumentEmployeeIdsTask.Result;
assignedEmployeeIds.AddRange(manageProjectEmployeeIds);
var finalEmployeeIds = assignedEmployeeIds.Intersect(viewDocumentEmployeeIds).ToList();
var data = new Dictionary<string, string>()
{
{ "Keyword", "Project_Document_Modefied" }
};
var registrationTokensForNotification = await _context.FCMTokenMappings.Where(ft => finalEmployeeIds.Contains(ft.EmployeeId) && ft.ExpiredAt >= DateTime.UtcNow).Select(ft => ft.FcmToken).ToListAsync();
await SendMessageToMultipleDevicesWithDataAsync(registrationTokensForNotification, notification, data);
}
#region =================================================================== Helper Functions ===================================================================
public async Task SendMessageToMultipleDevicesWithDataAsync(List<string> registrationTokens, Notification notificationFirebase, Dictionary<string, string> data)

View File

@ -28,5 +28,8 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task SendContactNoteAsync(List<Guid> bucketIds, Notification notification, Guid tenantId);
Task SendBucketAsync(Guid bucketId, Notification notification, Guid tenantId);
Task SendAssignBucketAsync(List<Guid> employeeIds, Notification notification, Guid tenantId);
Task SendEmployeeDocumentMessageAsync(Guid employeeId, Notification notification, Guid tenantId);
Task SendProjectDocumentMessageAsync(Guid projectId, Notification notification, Guid tenantId);
}
}