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.Services.Service;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis;
@ -27,16 +28,18 @@ namespace MarcoBMS.Services.Controllers
private readonly ProjectsHelper _projectsHelper;
private readonly UserHelper _userHelper;
private readonly S3UploadService _s3Service;
private readonly ILoggingService _logger;
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;
_employeeHelper = employeeHelper;
_projectsHelper = projectsHelper;
_userHelper = userHelper;
_s3Service = s3Service;
_logger = logger;
}
private int GetTenantId()
@ -56,10 +59,11 @@ namespace MarcoBMS.Services.Controllers
List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>();
foreach (var attendanceLog in lstAttendance)
{
string objectKey = attendanceLog.Document.S3Key;
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
string objectKey = attendanceLog.Document != null ? attendanceLog.Document.S3Key : string.Empty;
string preSignedUrl = string.IsNullOrEmpty(objectKey) ? _s3Service.GeneratePreSignedUrlAsync(objectKey) : string.Empty;
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));
}
@ -77,6 +81,7 @@ namespace MarcoBMS.Services.Controllers
}
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));
@ -98,15 +103,18 @@ namespace MarcoBMS.Services.Controllers
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));
}
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));
}
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));
}
@ -136,13 +144,14 @@ namespace MarcoBMS.Services.Controllers
{
result1.EmployeeAvatar = null;
result1.EmployeeId = teamMember.EmployeeId;
result1.FirstName = teamMember.Employee.FirstName;
result1.LastName = teamMember.Employee.LastName;
result1.FirstName = teamMember.Employee != null ? teamMember.Employee.FirstName : null;
result1.LastName = teamMember.Employee != null ? teamMember.Employee.LastName : null;
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));
}
@ -161,11 +170,13 @@ namespace MarcoBMS.Services.Controllers
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));
}
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));
}
@ -184,7 +195,7 @@ namespace MarcoBMS.Services.Controllers
foreach (ProjectAllocation teamMember in projectteam)
{
if (teamMember.Employee.JobRole != null)
if (teamMember.Employee != null && teamMember.Employee.JobRole != null)
{
var result1 = new EmployeeAttendanceVM()
{
@ -216,6 +227,7 @@ namespace MarcoBMS.Services.Controllers
//return x.FirstName.CompareTo(y.FirstName);
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));
}
@ -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<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 jobRole = await _context.JobRoles.ToListAsync();
@ -248,7 +260,7 @@ namespace MarcoBMS.Services.Controllers
};
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.LastName = teamMember.Employee.LastName;
@ -262,7 +274,7 @@ namespace MarcoBMS.Services.Controllers
{
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));
}
@ -277,6 +289,7 @@ namespace MarcoBMS.Services.Controllers
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
_logger.LogError("User sent Invalid Date while marking attendance");
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); ;
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);
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)
{
attendance.Comment = recordAttendanceDot.Comment;
if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN)
{
attendance.InTime = finalDateTime;
attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
}
@ -400,15 +422,17 @@ namespace MarcoBMS.Services.Controllers
Activity = attendance.Activity,
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));
}
_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));
}
catch (Exception ex)
{
await transaction.RollbackAsync(); // Rollback on failure
_logger.LogError("{Error} while marking attendance", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
}
@ -424,6 +448,7 @@ namespace MarcoBMS.Services.Controllers
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
_logger.LogError("User sent Invalid Date while marking attendance");
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); ;
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);
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)
{
attendance.Comment = recordAttendanceDot.Comment;
if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN)
{
attendance.InTime = finalDateTime;
attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
}
@ -566,7 +600,7 @@ namespace MarcoBMS.Services.Controllers
EmployeeID = recordAttendanceDot.EmployeeID,
Latitude = recordAttendanceDot.Latitude,
Longitude = recordAttendanceDot.Longitude,
DocumentId = document.Id,
DocumentId = document != null ? document.Id : null,
TenantId = TenantId,
UpdatedBy = recordAttendanceDot.EmployeeID,
UpdatedOn = recordAttendanceDot.Date
@ -600,8 +634,8 @@ namespace MarcoBMS.Services.Controllers
Activity = attendance.Activity,
JobRoleName = employee.JobRole.Name,
DocumentId = document.Id,
ThumbPreSignedUrl = preSignedUrl ?? string.Empty,
PreSignedUrl = preSignedUrl ?? string.Empty
ThumbPreSignedUrl = preSignedUrl,
PreSignedUrl = preSignedUrl
};
}
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));
}
_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));
}
catch (Exception ex)
{
await transaction.RollbackAsync(); // Rollback on failure
_logger.LogError("{Error} while marking attendance", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
}
}
private static DateTime GetDateFromTimeStamp(DateTime date, string timeString)
{
//DateTime date = recordAttendanceDot.Date;