Implement null validation in attendance log API #29

Merged
vikas.nale merged 2 commits from Ashutosh_Bug#117_Null_Validation_In_Attendance_Log into Feature_Forum 2025-04-29 05:45:16 +00:00

View File

@ -9,6 +9,7 @@ using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.AttendanceVM; using Marco.Pms.Model.ViewModels.AttendanceVM;
using Marco.Pms.Services.Service; using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
@ -27,16 +28,18 @@ namespace MarcoBMS.Services.Controllers
private readonly ProjectsHelper _projectsHelper; private readonly ProjectsHelper _projectsHelper;
private readonly UserHelper _userHelper; private readonly UserHelper _userHelper;
private readonly S3UploadService _s3Service; private readonly S3UploadService _s3Service;
private readonly ILoggingService _logger;
public AttendanceController( public AttendanceController(
ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper, S3UploadService s3Service) ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper, S3UploadService s3Service, ILoggingService logger)
{ {
_context = context; _context = context;
_employeeHelper = employeeHelper; _employeeHelper = employeeHelper;
_projectsHelper = projectsHelper; _projectsHelper = projectsHelper;
_userHelper = userHelper; _userHelper = userHelper;
_s3Service = s3Service; _s3Service = s3Service;
_logger = logger;
} }
private int GetTenantId() private int GetTenantId()
@ -56,10 +59,11 @@ namespace MarcoBMS.Services.Controllers
List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>(); List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>();
foreach (var attendanceLog in lstAttendance) foreach (var attendanceLog in lstAttendance)
{ {
string objectKey = attendanceLog.Document.S3Key; string objectKey = attendanceLog.Document != null ? attendanceLog.Document.S3Key : string.Empty;
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey); string preSignedUrl = string.IsNullOrEmpty(objectKey) ? _s3Service.GeneratePreSignedUrlAsync(objectKey) : string.Empty;
attendanceLogVMs.Add(attendanceLog.ToAttendanceLogVMFromAttendanceLog(preSignedUrl, preSignedUrl)); attendanceLogVMs.Add(attendanceLog.ToAttendanceLogVMFromAttendanceLog(preSignedUrl, preSignedUrl));
} }
_logger.LogInfo("{count} Attendance records fetched successfully", lstAttendance.Count);
return Ok(ApiResponse<object>.SuccessResponse(attendanceLogVMs, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200)); return Ok(ApiResponse<object>.SuccessResponse(attendanceLogVMs, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
} }
@ -77,6 +81,7 @@ namespace MarcoBMS.Services.Controllers
} }
List<AttendanceLog> lstAttendance = await _context.AttendanceLogs.Where(c => c.EmployeeID == employeeid && c.TenantId == TenantId).ToListAsync(); List<AttendanceLog> lstAttendance = await _context.AttendanceLogs.Where(c => c.EmployeeID == employeeid && c.TenantId == TenantId).ToListAsync();
_logger.LogInfo("{count} Attendance records fetched successfully", lstAttendance.Count);
return Ok(ApiResponse<object>.SuccessResponse(lstAttendance, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200)); return Ok(ApiResponse<object>.SuccessResponse(lstAttendance, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
@ -98,15 +103,18 @@ namespace MarcoBMS.Services.Controllers
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false) if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
{ {
_logger.LogError("User sent Invalid from Date while featching attendance logs");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
} }
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false) if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
{ {
_logger.LogError("User sent Invalid to Date while featching attendance logs");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
} }
if (projectId <= 0) if (projectId <= 0)
{ {
_logger.LogError("The project Id sent by user is less than or equal to zero");
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
} }
@ -136,13 +144,14 @@ namespace MarcoBMS.Services.Controllers
{ {
result1.EmployeeAvatar = null; result1.EmployeeAvatar = null;
result1.EmployeeId = teamMember.EmployeeId; result1.EmployeeId = teamMember.EmployeeId;
result1.FirstName = teamMember.Employee.FirstName; result1.FirstName = teamMember.Employee != null ? teamMember.Employee.FirstName : null;
result1.LastName = teamMember.Employee.LastName; result1.LastName = teamMember.Employee != null ? teamMember.Employee.LastName : null;
result.Add(result1); result.Add(result1);
} }
} }
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200)); return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
} }
@ -161,11 +170,13 @@ namespace MarcoBMS.Services.Controllers
if (date != null && DateTime.TryParse(date, out forDate) == false) if (date != null && DateTime.TryParse(date, out forDate) == false)
{ {
_logger.LogError("User sent Invalid Date while featching attendance logs");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
} }
if (projectId <= 0) if (projectId <= 0)
{ {
_logger.LogError("The project Id sent by user is less than or equal to zero");
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
} }
@ -184,7 +195,7 @@ namespace MarcoBMS.Services.Controllers
foreach (ProjectAllocation teamMember in projectteam) foreach (ProjectAllocation teamMember in projectteam)
{ {
if (teamMember.Employee.JobRole != null) if (teamMember.Employee != null && teamMember.Employee.JobRole != null)
{ {
var result1 = new EmployeeAttendanceVM() var result1 = new EmployeeAttendanceVM()
{ {
@ -216,6 +227,7 @@ namespace MarcoBMS.Services.Controllers
//return x.FirstName.CompareTo(y.FirstName); //return x.FirstName.CompareTo(y.FirstName);
return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal); return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
}); });
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200)); return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
} }
@ -230,7 +242,7 @@ namespace MarcoBMS.Services.Controllers
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.TenantId == TenantId).ToListAsync(); List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.TenantId == TenantId).ToListAsync();
List<ProjectAllocation> projectteam = await _projectsHelper.GetTeamByProject(TenantId, projectId, IncludeInActive); List<ProjectAllocation> projectteam = await _projectsHelper.GetTeamByProject(TenantId, projectId, true);
var idList = projectteam.Select(p => p.EmployeeId).ToList(); var idList = projectteam.Select(p => p.EmployeeId).ToList();
var jobRole = await _context.JobRoles.ToListAsync(); var jobRole = await _context.JobRoles.ToListAsync();
@ -248,7 +260,7 @@ namespace MarcoBMS.Services.Controllers
}; };
var teamMember = projectteam.Find(m => m.EmployeeId == attende.EmployeeID); var teamMember = projectteam.Find(m => m.EmployeeId == attende.EmployeeID);
if (teamMember != null && teamMember.Employee.JobRole != null) if (teamMember != null && teamMember.Employee != null && teamMember.Employee.JobRole != null)
{ {
result1.FirstName = teamMember.Employee.FirstName; result1.FirstName = teamMember.Employee.FirstName;
result1.LastName = teamMember.Employee.LastName; result1.LastName = teamMember.Employee.LastName;
@ -262,7 +274,7 @@ namespace MarcoBMS.Services.Controllers
{ {
return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal); return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
}); });
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200)); return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
} }
@ -277,6 +289,7 @@ namespace MarcoBMS.Services.Controllers
.SelectMany(v => v.Errors) .SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage) .Select(e => e.ErrorMessage)
.ToList(); .ToList();
_logger.LogError("User sent Invalid Date while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
} }
@ -287,16 +300,25 @@ namespace MarcoBMS.Services.Controllers
{ {
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ; Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ;
if (recordAttendanceDot.MarkTime == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400)); if (recordAttendanceDot.MarkTime == null)
{
_logger.LogError("User sent Invalid Mark Time while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
}
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime); DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
if (recordAttendanceDot.Comment == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400)); if (recordAttendanceDot.Comment == null)
{
_logger.LogError("User sent Invalid comment while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
}
if (attendance != null) if (attendance != null)
{ {
attendance.Comment = recordAttendanceDot.Comment; attendance.Comment = recordAttendanceDot.Comment;
if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN) if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN)
{ {
attendance.InTime = finalDateTime;
attendance.OutTime = null; attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT; attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
} }
@ -400,15 +422,17 @@ namespace MarcoBMS.Services.Controllers
Activity = attendance.Activity, Activity = attendance.Activity,
JobRoleName = employee.JobRole.Name JobRoleName = employee.JobRole.Name
}; };
_logger.LogInfo("Attendance for employee {FirstName} {LastName} has been marked", employee.FirstName ?? string.Empty, employee.LastName ?? string.Empty);
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200)); 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);
return Ok(ApiResponse<object>.SuccessResponse(new EmployeeAttendanceVM(), "Attendance marked successfully.", 200)); return Ok(ApiResponse<object>.SuccessResponse(new EmployeeAttendanceVM(), "Attendance marked successfully.", 200));
} }
catch (Exception ex) catch (Exception ex)
{ {
await transaction.RollbackAsync(); // Rollback on failure await transaction.RollbackAsync(); // Rollback on failure
_logger.LogError("{Error} while marking attendance", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
} }
@ -424,6 +448,7 @@ namespace MarcoBMS.Services.Controllers
.SelectMany(v => v.Errors) .SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage) .Select(e => e.ErrorMessage)
.ToList(); .ToList();
_logger.LogError("User sent Invalid Date while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400)); return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
} }
@ -434,16 +459,25 @@ namespace MarcoBMS.Services.Controllers
{ {
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ; Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ;
if (recordAttendanceDot.MarkTime == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400)); if (recordAttendanceDot.MarkTime == null)
{
_logger.LogError("User sent Invalid Mark Time while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
}
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime); DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
if (recordAttendanceDot.Comment == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400)); if (recordAttendanceDot.Comment == null)
{
_logger.LogError("User sent Invalid comment while marking attendance");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
}
if (attendance != null) if (attendance != null)
{ {
attendance.Comment = recordAttendanceDot.Comment; attendance.Comment = recordAttendanceDot.Comment;
if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN) if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN)
{ {
attendance.InTime = finalDateTime;
attendance.OutTime = null; attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT; attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
} }
@ -566,7 +600,7 @@ namespace MarcoBMS.Services.Controllers
EmployeeID = recordAttendanceDot.EmployeeID, EmployeeID = recordAttendanceDot.EmployeeID,
Latitude = recordAttendanceDot.Latitude, Latitude = recordAttendanceDot.Latitude,
Longitude = recordAttendanceDot.Longitude, Longitude = recordAttendanceDot.Longitude,
DocumentId = document.Id, DocumentId = document != null ? document.Id : null,
TenantId = TenantId, TenantId = TenantId,
UpdatedBy = recordAttendanceDot.EmployeeID, UpdatedBy = recordAttendanceDot.EmployeeID,
UpdatedOn = recordAttendanceDot.Date UpdatedOn = recordAttendanceDot.Date
@ -600,8 +634,8 @@ namespace MarcoBMS.Services.Controllers
Activity = attendance.Activity, Activity = attendance.Activity,
JobRoleName = employee.JobRole.Name, JobRoleName = employee.JobRole.Name,
DocumentId = document.Id, DocumentId = document.Id,
ThumbPreSignedUrl = preSignedUrl ?? string.Empty, ThumbPreSignedUrl = preSignedUrl,
PreSignedUrl = preSignedUrl ?? string.Empty PreSignedUrl = preSignedUrl
}; };
} }
else else
@ -623,19 +657,21 @@ namespace MarcoBMS.Services.Controllers
}; };
} }
_logger.LogInfo("Attendance for employee {FirstName} {LastName} has been marked", employee.FirstName ?? string.Empty, employee.LastName ?? string.Empty);
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200)); 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);
return Ok(ApiResponse<object>.SuccessResponse(new EmployeeAttendanceVM(), "Attendance marked successfully.", 200)); return Ok(ApiResponse<object>.SuccessResponse(new EmployeeAttendanceVM(), "Attendance marked successfully.", 200));
} }
catch (Exception ex) catch (Exception ex)
{ {
await transaction.RollbackAsync(); // Rollback on failure await transaction.RollbackAsync(); // Rollback on failure
_logger.LogError("{Error} while marking attendance", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
} }
} }
private static DateTime GetDateFromTimeStamp(DateTime date, string timeString) private static DateTime GetDateFromTimeStamp(DateTime date, string timeString)
{ {
//DateTime date = recordAttendanceDot.Date; //DateTime date = recordAttendanceDot.Date;