Added firebase in attendance record API

This commit is contained in:
ashutosh.nehete 2025-08-13 15:15:14 +05:30
parent 58b817be99
commit 813bc70bda
4 changed files with 130 additions and 36 deletions

View File

@ -1,5 +1,4 @@
using FirebaseAdmin.Messaging;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.AttendanceModule;
using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Employees;
@ -36,10 +35,11 @@ namespace MarcoBMS.Services.Controllers
private readonly PermissionServices _permission;
private readonly ILoggingService _logger;
private readonly IHubContext<MarcoHub> _signalR;
private readonly IFirebaseService _firebase;
public AttendanceController(
ApplicationDbContext context, EmployeeHelper employeeHelper, IProjectServices projectServices, UserHelper userHelper, S3UploadService s3Service, ILoggingService logger, PermissionServices permission, IHubContext<MarcoHub> signalR)
ApplicationDbContext context, EmployeeHelper employeeHelper, IProjectServices projectServices, UserHelper userHelper,
S3UploadService s3Service, ILoggingService logger, PermissionServices permission, IHubContext<MarcoHub> signalR, IFirebaseService firebase)
{
_context = context;
_employeeHelper = employeeHelper;
@ -49,6 +49,7 @@ namespace MarcoBMS.Services.Controllers
_logger = logger;
_permission = permission;
_signalR = signalR;
_firebase = firebase;
}
private Guid GetTenantId()
@ -82,8 +83,8 @@ namespace MarcoBMS.Services.Controllers
return Ok(ApiResponse<object>.SuccessResponse(attendanceLogVMs, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
}
[HttpGet("log/employee/{employeeId}")]
[HttpGet("log/employee/{employeeId}")]
public async Task<IActionResult> GetAttendanceLogByEmployeeId(Guid employeeId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
{
Guid TenantId = GetTenantId();
@ -259,7 +260,6 @@ namespace MarcoBMS.Services.Controllers
/// <param name="date">YYYY-MM-dd</param>
/// <returns></returns>
[HttpGet("project/team")]
public async Task<IActionResult> EmployeeAttendanceByProject([FromQuery] Guid projectId, [FromQuery] bool IncludeInActive, [FromQuery] string? date = null)
{
Guid TenantId = GetTenantId();
@ -364,7 +364,6 @@ namespace MarcoBMS.Services.Controllers
}
[HttpGet("regularize")]
public async Task<IActionResult> GetRequestRegularizeAttendance([FromQuery] Guid projectId, [FromQuery] bool IncludeInActive)
{
Guid TenantId = GetTenantId();
@ -578,6 +577,19 @@ namespace MarcoBMS.Services.Controllers
var notification = new { LoggedInUserId = currentEmployee.Id, Keyword = "Attendance", Activity = sendActivity, ProjectId = attendance.ProjectID, Response = vm };
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
_logger.LogInfo("Attendance for employee {FirstName} {LastName} has been marked", employee.FirstName ?? string.Empty, employee.LastName ?? string.Empty);
_ = 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 = $"{vm.FirstName} {vm.LastName}";
await _firebase.SendAttendanceMessageAsync(attendance.ProjectID, name, recordAttendanceDot.Action, TenantId);
});
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200));
}
_logger.LogInfo("Attendance for employee {FirstName} {LastName} has been marked", employee.FirstName ?? string.Empty, employee.LastName ?? string.Empty);
@ -775,20 +787,19 @@ namespace MarcoBMS.Services.Controllers
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
_logger.LogInfo("Attendance recorded for employee: {FullName}", $"{employee.FirstName} {employee.LastName}");
var message = new Message()
_ = Task.Run(async () =>
{
Token = recordAttendanceDot.DeviceToken,
Notification = new Notification
{
Title = "Hello from .NET",
Body = "This is a test message"
}
};
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
_logger.LogInfo("Firebase push notification messageId: {MessageId}", response);
// --- 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 = $"{vm.FirstName} {vm.LastName}";
await _firebase.SendAttendanceMessageAsync(attendance.ProjectID, name, recordAttendanceDot.Action, tenantId);
});
_logger.LogInfo("Attendance recorded for employee: {FullName}", $"{employee.FirstName} {employee.LastName}");
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200));
}
catch (Exception ex)

View File

@ -1,4 +1,5 @@
using Marco.Pms.DataAccess.Data;
using FirebaseAdmin.Messaging;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Authentication;
using Marco.Pms.Model.Dtos.Authentication;
using Marco.Pms.Model.Dtos.Util;
@ -256,7 +257,14 @@ namespace MarcoBMS.Services.Controllers
// --- 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.
await _firebase.SendMessageToMultipleDevicesAsync();
var notification = new Notification
{
Title = "Testing from API",
Body = "This messages comes from FireBase Services"
};
await _firebase.SendLoginMessageAsync(notification);
});
return Ok(ApiResponse<object>.SuccessResponse(responseData, "User logged in successfully.", 200));

View File

@ -1,5 +1,7 @@
using FirebaseAdmin.Messaging;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Service;
using Microsoft.EntityFrameworkCore;
@ -28,30 +30,99 @@ namespace Marco.Pms.Services.Service
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
}
public async Task SendMessageToMultipleDevicesAsync()
public async Task SendLoginMessageAsync(Notification notificationFirebase)
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
// List of device registration tokens to send the message to
var registrationTokens = await _context.FCMTokenMappings.Select(ft => ft.FcmToken).ToListAsync();
//var registrationTokens = new List<string>
//{
// "YOUR_REGISTRATION_TOKEN_1",
// "YOUR_REGISTRATION_TOKEN_2",
// // add up to 500 tokens
//};
var message = new MulticastMessage()
await SendMessageToMultipleDevicesAsync(registrationTokens, notificationFirebase);
}
public async Task SendAttendanceMessageAsync(Guid projectId, string Name, ATTENDANCE_MARK_TYPE markType, Guid tenantId)
{
await using var _context = await _dbContextFactory.CreateDbContextAsync();
var projectTask = Task.Run(async () =>
{
Tokens = registrationTokens,
Notification = new Notification
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
{
Title = "Testing from API",
Body = "This messages comes from FireBase Services"
}
ProjectName = g.Select(pa => pa.Project!.Name).FirstOrDefault(),
EmployeeIds = g.Select(pa => pa.EmployeeId).Distinct().ToList()
}).FirstOrDefaultAsync();
});
var roleTask = Task.Run(async () =>
{
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.RolePermissionMappings
.Where(rp => rp.FeaturePermissionId == PermissionsMaster.TeamAttendance)
.Select(rp => rp.ApplicationRoleId).ToListAsync();
});
await Task.WhenAll(projectTask, roleTask);
var applicationRoleIds = roleTask.Result;
var project = projectTask.Result;
List<Guid> projectAssignedEmployeeIds = project?.EmployeeIds ?? new List<Guid>();
var employeeIds = await _context.EmployeeRoleMappings
.Where(er => projectAssignedEmployeeIds.Contains(er.EmployeeId) && applicationRoleIds.Contains(er.RoleId))
.Select(er => er.RoleId)
.ToListAsync();
string body;
switch (markType)
{
case ATTENDANCE_MARK_TYPE.CHECK_IN:
body = $"{Name} Checked In for project {project?.ProjectName ?? ""}";
break;
case ATTENDANCE_MARK_TYPE.CHECK_OUT:
body = $"{Name} Checked Out for project {project?.ProjectName ?? ""}";
break;
case ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE:
body = $"{Name} Requested Regularization for project {project?.ProjectName ?? ""}";
break;
case ATTENDANCE_MARK_TYPE.REGULARIZE:
body = $"Regularization Accepted of {Name} for Project {project?.ProjectName ?? ""}";
break;
case ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT:
body = $"Regularization Rejected of {Name} for Project {project?.ProjectName ?? ""}";
break;
default:
body = string.Empty;
break;
}
var notificationFirebase = new Notification
{
Title = "Attendance Marked",
Body = body
};
// List of device registration tokens to send the message to
var registrationTokens = await _context.FCMTokenMappings
//.Where(ft => employeeIds.Contains(ft.EmployeeId) && ft.TenantId == tenantId)
.Select(ft => ft.FcmToken).ToListAsync();
await SendMessageToMultipleDevicesAsync(registrationTokens, notificationFirebase);
}
public async Task SendMessageToMultipleDevicesAsync(List<string> registrationTokens, Notification notificationFirebase)
{
try
{
var message = new MulticastMessage()
{
Tokens = registrationTokens,
Notification = notificationFirebase
};
// Send the multicast message
var response = await FirebaseMessaging.DefaultInstance.SendEachForMulticastAsync(message);
_logger.LogInfo("{SuccessCount} messages were sent successfully.", response.SuccessCount);

View File

@ -1,7 +1,11 @@
namespace Marco.Pms.Services.Service.ServiceInterfaces
using FirebaseAdmin.Messaging;
using Marco.Pms.Model.Dtos.Attendance;
namespace Marco.Pms.Services.Service.ServiceInterfaces
{
public interface IFirebaseService
{
Task SendMessageToMultipleDevicesAsync();
Task SendLoginMessageAsync(Notification notificationFirebase);
Task SendAttendanceMessageAsync(Guid projectId, string Name, ATTENDANCE_MARK_TYPE markType, Guid tenantId);
}
}