Added the API to get latest tagging entitry for current employee

This commit is contained in:
ashutosh.nehete 2025-11-17 12:03:06 +05:30
parent 08a336be37
commit 897537a60c
4 changed files with 73 additions and 10 deletions

View File

@ -6,14 +6,11 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
public class JobAttendanceVM
{
public Guid Id { get; set; }
public Guid JobTcketId { get; set; }
public BasicJobTicketVM? JobTicket { get; set; }
public TAGGING_MARK_TYPE Action { get; set; }
public TAGGING_MARK_TYPE? Action { get; set; }
public TAGGING_MARK_TYPE? NextAction { get; set; }
public BasicEmployeeVM? Employee { get; set; }
public DateTime TaggedInTime { get; set; }
public DateTime? TaggedInTime { get; set; }
public DateTime? TaggedOutTime { get; set; }
public DateTime TaggedInAt { get; set; }
public DateTime? TaggedOutAt { get; set; }
}
}

View File

@ -262,7 +262,16 @@ namespace Marco.Pms.Services.Controllers
#region =================================================================== Job Tagging Functions ===================================================================
[HttpGet("job/attendance/team")]
[HttpGet("job/attendance/self/{jobTicketId}")]
public async Task<IActionResult> GetAttendanceForSelf(Guid jobTicketId)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _serviceProject.GetAttendanceForSelfAsync(jobTicketId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpGet("job/attendance/team/history")]
public async Task<IActionResult> GetAttendanceForJobTeam([FromQuery] Guid jobTicketId, [FromQuery] DateTime? fromDate, [FromQuery] DateTime? toDate)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();

View File

@ -37,6 +37,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
#endregion
#region =================================================================== Job Tagging Functions ===================================================================
Task<ApiResponse<object>> GetAttendanceForSelfAsync(Guid jobTicketId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetAttendanceForJobTeamAsync(Guid jobTicketId, DateTime? startDate, DateTime? endDate, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> ManageJobTaggingAsync(JobAttendanceDto model, Employee loggedInEmployee, Guid tenantId);
#endregion

View File

@ -2014,6 +2014,63 @@ namespace Marco.Pms.Services.Service
#endregion
#region =================================================================== Job Tagging Functions ===================================================================
public async Task<ApiResponse<object>> GetAttendanceForSelfAsync(Guid jobTicketId, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("GetAttendanceForSelfAsync initiated for EmployeeId: {EmployeeId}, JobTicketId: {JobTicketId}", loggedInEmployee.Id, jobTicketId);
try
{
// Validate existence of the Job Ticket with related Status
var jobTicket = await _context.JobTickets
.AsNoTracking()
.Include(jt => jt.Status)
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && jt.IsActive);
if (jobTicket == null)
{
_logger.LogWarning("JobTicket not found. JobTicketId: {JobTicketId}, TenantId: {TenantId}", jobTicketId, tenantId);
return ApiResponse<object>.ErrorResponse("Job not found", "Job is not found", 404);
}
// Fetch the most recent attendance record for the logged-in employee for the specified job
var jobAttendance = await _context.JobAttendance
.AsNoTracking()
.Include(ja => ja.JobTicket).ThenInclude(jt => jt!.Status)
.Include(ja => ja.Employee).ThenInclude(e => e!.JobRole)
.Where(ja => ja.JobTcketId == jobTicketId && ja.EmployeeId == loggedInEmployee.Id && ja.TenantId == tenantId)
.OrderByDescending(ja => ja.TaggedInTime)
.FirstOrDefaultAsync();
JobAttendanceVM response;
// If no attendance record exists or last record is tagged out or for a different day, prepare a default response with next action TAG_IN
if (jobAttendance == null || (jobAttendance.TaggedOutTime.HasValue && jobAttendance.TaggedInTime.Date != DateTime.UtcNow.Date))
{
response = new JobAttendanceVM
{
JobTicket = _mapper.Map<BasicJobTicketVM>(jobTicket),
Employee = _mapper.Map<BasicEmployeeVM>(loggedInEmployee),
NextAction = TAGGING_MARK_TYPE.TAG_IN
};
_logger.LogInfo("No current active attendance found for EmployeeId: {EmployeeId}. Prompting to TAG_IN.", loggedInEmployee.Id);
}
else
{
// Active attendance exists, returning last attendance with details
response = _mapper.Map<JobAttendanceVM>(jobAttendance);
_logger.LogInfo("Latest attendance fetched for EmployeeId: {EmployeeId} on JobTicketId: {JobTicketId}", loggedInEmployee.Id, jobTicketId);
}
// Return success with the constructed response
return ApiResponse<object>.SuccessResponse(response, "Latest job tagging for current employee fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception in GetAttendanceForSelfAsync for EmployeeId: {EmployeeId}, JobTicketId: {JobTicketId}", loggedInEmployee.Id, jobTicketId);
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> GetAttendanceForJobTeamAsync(Guid jobTicketId, DateTime? startDate, DateTime? endDate, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("GetAttendanceForJobTeamAsync called for JobTicketId: {JobTicketId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}", jobTicketId, tenantId, loggedInEmployee.Id);
@ -2023,7 +2080,6 @@ namespace Marco.Pms.Services.Service
// Validate the existence and active status of the job ticket including its status related data
var jobTicket = await _context.JobTickets
.AsNoTracking()
.Include(jt => jt.Status)
.FirstOrDefaultAsync(jt => jt.Id == jobTicketId && jt.TenantId == tenantId && jt.IsActive);
if (jobTicket == null)
@ -2039,8 +2095,8 @@ namespace Marco.Pms.Services.Service
// Fetch attendance records within the date range for the specified job ticket and tenant
var attendances = await _context.JobAttendance
.AsNoTracking()
.Include(ja => ja.JobTicket).ThenInclude(jt => jt.Status)
.Include(ja => ja.Employee).ThenInclude(e => e.JobRole)
.Include(ja => ja.JobTicket).ThenInclude(jt => jt!.Status)
.Include(ja => ja.Employee).ThenInclude(e => e!.JobRole)
.Where(ja => ja.JobTcketId == jobTicketId
&& ja.TaggedInTime.Date >= fromDate
&& ja.TaggedInTime.Date <= toDate
@ -2054,7 +2110,7 @@ namespace Marco.Pms.Services.Service
// Determine if current attendance record is not the latest, if so clear NextAction
var isNotLast = attendances.Any(attendance => attendance.TaggedInTime.Date > ja.TaggedInTime.Date);
if (isNotLast || (ja.TaggedOutTime.HasValue && ja.TaggedInTime.Date != DateTime.UtcNow.Date))
if (isNotLast || (ja.TaggedOutTime.HasValue && ja.TaggedInTime.Date != DateTime.UtcNow.Date) || ja.EmployeeId != loggedInEmployee.Id)
{
result.NextAction = null;
}