Added an API to get logs of certain attendance

This commit is contained in:
ashutosh.nehete 2025-11-17 13:06:24 +05:30
parent 897537a60c
commit bd14424062
5 changed files with 115 additions and 0 deletions

View File

@ -0,0 +1,20 @@
using Marco.Pms.Model.ServiceProject;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.DocumentManager;
namespace Marco.Pms.Model.ViewModels.ServiceProject
{
public class JobAttendanceLogVM
{
public Guid Id { get; set; }
public BasicJobTicketVM? JobTicket { get; set; }
public BasicDocumentVM? Document { get; set; }
public string? Latitude { get; set; }
public string? Longitude { get; set; }
public TAGGING_MARK_TYPE Action { get; set; }
public string? Comment { get; set; }
public BasicEmployeeVM? Employee { get; set; }
public DateTime MarkedTIme { get; set; }
public DateTime MarkedAt { get; set; }
}
}

View File

@ -271,6 +271,15 @@ namespace Marco.Pms.Services.Controllers
return StatusCode(response.StatusCode, response);
}
[HttpGet("job/attendance/log/{attendanceId}")]
public async Task<IActionResult> GetAttendanceLogForAttendance(Guid attendanceId)
{
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _serviceProject.GetAttendanceLogForAttendanceAsync(attendanceId, 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)
{

View File

@ -212,6 +212,7 @@ namespace Marco.Pms.Services.MappingProfiles
CreateMap<JobComment, JobCommentVM>();
CreateMap<JobAttendanceLog, JobAttendanceLogVM>();
CreateMap<JobAttendance, JobAttendanceVM>()
.ForMember(
dest => dest.NextAction,
@ -509,6 +510,10 @@ namespace Marco.Pms.Services.MappingProfiles
#region ======================================================= Document =======================================================
CreateMap<Document, DocumentVM>();
CreateMap<Document, BasicDocumentVM>()
.ForMember(
dest => dest.DocumentId,
opt => opt.MapFrom(src => src.Id));
CreateMap<DocumentMongoDB, BasicDocumentVM>()
.ForMember(
dest => dest.DocumentId,

View File

@ -38,6 +38,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
#region =================================================================== Job Tagging Functions ===================================================================
Task<ApiResponse<object>> GetAttendanceForSelfAsync(Guid jobTicketId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetAttendanceLogForAttendanceAsync(Guid jobAttendanceId, 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

@ -9,6 +9,7 @@ using Marco.Pms.Model.MongoDBModels.Utility;
using Marco.Pms.Model.ServiceProject;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.AttendanceVM;
using Marco.Pms.Model.ViewModels.DocumentManager;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Model.ViewModels.Organization;
@ -2070,6 +2071,84 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", ex.Message, 500);
}
}
public async Task<ApiResponse<object>> GetAttendanceLogForAttendanceAsync(Guid jobAttendanceId, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("GetAttendanceLogForAttendanceAsync called for JobAttendanceId: {JobAttendanceId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}", jobAttendanceId, tenantId, loggedInEmployee.Id);
try
{
// Validate existence of the JobAttendance record for the tenant
var jobAttendance = await _context.JobAttendance
.AsNoTracking()
.FirstOrDefaultAsync(ja => ja.Id == jobAttendanceId && ja.TenantId == tenantId);
if (jobAttendance == null)
{
_logger.LogWarning("JobAttendance not found. JobAttendanceId: {JobAttendanceId}, TenantId: {TenantId}", jobAttendanceId, tenantId);
return ApiResponse<object>.ErrorResponse("Job attendance not found", "Job attendance not found", 404);
}
// Fetch related attendance logs including JobTicket status and Employee role details
var attendanceLogs = await _context.JobAttendanceLogs
.AsNoTracking()
.Include(jal => jal.JobTicket).ThenInclude(jt => jt!.Status)
.Include(jal => jal.Employee).ThenInclude(e => e!.JobRole)
.Where(jal => jal.JobAttendanceId == jobAttendanceId && jal.TenantId == tenantId)
.ToListAsync();
// If no logs found, return empty list with success message
if (!attendanceLogs.Any())
{
_logger.LogInfo("No attendance logs found for JobAttendanceId: {JobAttendanceId}", jobAttendanceId);
return ApiResponse<object>.SuccessResponse(new List<AttendanceLogVM>(), "Job attendance log fetched successfully", 200);
}
// Extract document IDs from logs that have attached documents
var documentIds = attendanceLogs.Where(log => log.DocumentId.HasValue)
.Select(log => log.DocumentId!.Value)
.Distinct()
.ToList();
// Fetch documents related to the extracted document IDs and tenant
var documents = await _context.Documents
.AsNoTracking()
.Where(d => documentIds.Contains(d.Id) && d.TenantId == tenantId)
.ToListAsync();
// Map each attendance log and enrich with document info including pre-signed URLs
var response = attendanceLogs.Select(log =>
{
var logVm = _mapper.Map<JobAttendanceLogVM>(log);
if (log.DocumentId.HasValue)
{
var document = documents.FirstOrDefault(d => d.Id == log.DocumentId.Value);
if (document != null)
{
var preSignedUrl = _s3Service.GeneratePreSignedUrl(document.S3Key);
var thumbPreSignedUrl = !string.IsNullOrWhiteSpace(document.ThumbS3Key)
? _s3Service.GeneratePreSignedUrl(document.ThumbS3Key)
: preSignedUrl;
logVm.Document = _mapper.Map<BasicDocumentVM>(document);
logVm.Document.PreSignedUrl = preSignedUrl;
logVm.Document.ThumbPreSignedUrl = thumbPreSignedUrl;
}
}
return logVm;
}).ToList();
_logger.LogInfo("Job attendance log fetched successfully. JobAttendanceId: {JobAttendanceId}, RecordsCount: {Count}", jobAttendanceId, response.Count);
return ApiResponse<object>.SuccessResponse(response, "Job attendance log fetched successfully", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception in GetAttendanceLogForAttendanceAsync for JobAttendanceId: {JobAttendanceId}, TenantId: {TenantId}", jobAttendanceId, tenantId);
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)
{
@ -2137,6 +2216,7 @@ namespace Marco.Pms.Services.Service
// Validate the job ticket existence and status
var jobTicket = await _context.JobTickets
.AsNoTracking()
.Include(jt => jt.Status)
.FirstOrDefaultAsync(jt => jt.Id == model.JobTcketId && jt.TenantId == tenantId && jt.IsActive);
if (jobTicket == null)
{