Added the action and next action in get job details API for current employee

This commit is contained in:
ashutosh.nehete 2025-11-17 16:28:11 +05:30
parent 863f0ce8e2
commit 64cb2e0671
2 changed files with 97 additions and 3 deletions

View File

@ -16,6 +16,8 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
public DateTime StartDate { get; set; } public DateTime StartDate { get; set; }
public DateTime DueDate { get; set; } public DateTime DueDate { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public TAGGING_MARK_TYPE? TaggingAction { get; set; }
public TAGGING_MARK_TYPE? NextTaggingAction { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; } public BasicEmployeeVM? CreatedBy { get; set; }
public List<TagVM>? Tags { get; set; } public List<TagVM>? Tags { get; set; }

View File

@ -956,6 +956,9 @@ namespace Marco.Pms.Services.Service
await Task.WhenAll(assigneeTask, tagTask, updateLogTask); await Task.WhenAll(assigneeTask, tagTask, updateLogTask);
var assignees = assigneeTask.Result;
var isAssigned = assignees.Any(e => e.Id == loggedInEmployee.Id);
// Map update logs with status descriptions // Map update logs with status descriptions
var jobUpdateLogVMs = updateLogTask.Result.Select(ul => var jobUpdateLogVMs = updateLogTask.Result.Select(ul =>
{ {
@ -972,7 +975,7 @@ namespace Marco.Pms.Services.Service
}).ToList(); }).ToList();
// Map assignees, and tags to their respective viewmodels // Map assignees, and tags to their respective viewmodels
var assigneeVMs = _mapper.Map<List<BasicEmployeeVM>>(assigneeTask.Result); var assigneeVMs = _mapper.Map<List<BasicEmployeeVM>>(assignees);
var tagVMs = _mapper.Map<List<TagVM>>(tagTask.Result); var tagVMs = _mapper.Map<List<TagVM>>(tagTask.Result);
// Map main job ticket DTO and attach related data // Map main job ticket DTO and attach related data
@ -981,6 +984,31 @@ namespace Marco.Pms.Services.Service
response.Tags = tagVMs; response.Tags = tagVMs;
response.UpdateLogs = jobUpdateLogVMs; response.UpdateLogs = jobUpdateLogVMs;
if (isAssigned)
{
// Fetch the most recent attendance record for the logged-in employee for the specified job
var jobAttendance = await _context.JobAttendance
.AsNoTracking()
.Where(ja => ja.JobTcketId == jobTicket.Id && ja.EmployeeId == loggedInEmployee.Id && ja.TenantId == tenantId)
.OrderByDescending(ja => ja.TaggedInTime)
.FirstOrDefaultAsync();
// 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.NextTaggingAction = 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
response.TaggingAction = jobAttendance.Action;
response.NextTaggingAction = jobAttendance.Action == TAGGING_MARK_TYPE.TAG_IN ? TAGGING_MARK_TYPE.TAG_OUT : TAGGING_MARK_TYPE.TAG_IN;
_logger.LogInfo("Latest attendance fetched for EmployeeId: {EmployeeId} on JobTicketId: {JobTicketId}", loggedInEmployee.Id, jobTicket.Id);
}
}
_logger.LogInfo("Job ticket details assembled successfully for JobTicketId: {JobTicketId}", id); _logger.LogInfo("Job ticket details assembled successfully for JobTicketId: {JobTicketId}", id);
return ApiResponse<object>.SuccessResponse(response, "Job details fetched successfully", 200); return ApiResponse<object>.SuccessResponse(response, "Job details fetched successfully", 200);
@ -1937,7 +1965,7 @@ namespace Marco.Pms.Services.Service
var documentIds = deleteBillAttachments.Select(d => d.DocumentId!.Value).ToList(); var documentIds = deleteBillAttachments.Select(d => d.DocumentId!.Value).ToList();
try try
{ {
await DeleteAttachemnts(documentIds); await DeleteJobAttachemnts(documentIds);
_logger.LogInfo("{Count} attachments deleted for comment {CommentId} by employee {EmployeeId}", deleteBillAttachments.Count, id, loggedInEmployee.Id); _logger.LogInfo("{Count} attachments deleted for comment {CommentId} by employee {EmployeeId}", deleteBillAttachments.Count, id, loggedInEmployee.Id);
} }
catch (DbUpdateException dbEx) catch (DbUpdateException dbEx)
@ -2043,6 +2071,24 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Job not found", "Job is not found", 404); return ApiResponse<object>.ErrorResponse("Job not found", "Job is not found", 404);
} }
var jobEmployeeMapping = await _context.JobEmployeeMappings
.Where(jem => jem.AssigneeId == loggedInEmployee.Id && jem.JobTicketId == jobTicketId && jem.TenantId == tenantId)
.FirstOrDefaultAsync();
// Check if the job-to-employee mapping is null, indicating no assignment
if (jobEmployeeMapping == null)
{
// Log the error with relevant context for diagnostics
_logger.LogWarning("Tagging failed: Employee is not assigned to the job. JobId: {JobId}, EmployeeId: {EmployeeId}", jobTicketId, loggedInEmployee.Id);
// Return a structured error response with meaningful message and HTTP 400 Bad Request code
return ApiResponse<object>.ErrorResponse(
"Tagging operation failed because the employee is not assigned to this job.",
$"No job-employee mapping found for JobId: {jobTicketId} and EmployeeId: {loggedInEmployee.Id}.",
statusCode: 400);
}
// Fetch the most recent attendance record for the logged-in employee for the specified job // Fetch the most recent attendance record for the logged-in employee for the specified job
var jobAttendance = await _context.JobAttendance var jobAttendance = await _context.JobAttendance
.AsNoTracking() .AsNoTracking()
@ -2395,7 +2441,52 @@ namespace Marco.Pms.Services.Service
#region =================================================================== Helper Functions =================================================================== #region =================================================================== Helper Functions ===================================================================
private async Task DeleteAttachemnts(List<Guid> documentIds) //private async Task DeleteTalkingPointAttachments(List<Guid> documentIds)
//{
// using var scope = _serviceScopeFactory.CreateScope();
// var _updateLogHelper = scope.ServiceProvider.GetRequiredService<UtilityMongoDBHelper>();
// var attachmentTask = Task.Run(async () =>
// {
// await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
// var attachments = await dbContext.TalkingPointAttachments.AsNoTracking().Where(ba => documentIds.Contains(ba.DocumentId)).ToListAsync();
// dbContext.TalkingPointAttachments.RemoveRange(attachments);
// await dbContext.SaveChangesAsync();
// });
// var documentsTask = Task.Run(async () =>
// {
// await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
// var documents = await dbContext.Documents.AsNoTracking().Where(ba => documentIds.Contains(ba.Id)).ToListAsync();
// if (documents.Any())
// {
// dbContext.Documents.RemoveRange(documents);
// await dbContext.SaveChangesAsync();
// List<S3DeletionObject> deletionObject = new List<S3DeletionObject>();
// foreach (var document in documents)
// {
// deletionObject.Add(new S3DeletionObject
// {
// Key = document.S3Key
// });
// if (!string.IsNullOrWhiteSpace(document.ThumbS3Key) && document.ThumbS3Key != document.S3Key)
// {
// deletionObject.Add(new S3DeletionObject
// {
// Key = document.ThumbS3Key
// });
// }
// }
// await _updateLogHelper.PushToS3DeletionAsync(deletionObject);
// }
// });
// await Task.WhenAll(attachmentTask, documentsTask);
//}
private async Task DeleteJobAttachemnts(List<Guid> documentIds)
{ {
using var scope = _serviceScopeFactory.CreateScope(); using var scope = _serviceScopeFactory.CreateScope();
var _updateLogHelper = scope.ServiceProvider.GetRequiredService<UtilityMongoDBHelper>(); var _updateLogHelper = scope.ServiceProvider.GetRequiredService<UtilityMongoDBHelper>();
@ -2514,6 +2605,7 @@ namespace Marco.Pms.Services.Service
var jobStatusMapping = await statusMappingQuery.FirstOrDefaultAsync(); var jobStatusMapping = await statusMappingQuery.FirstOrDefaultAsync();
return jobStatusMapping; return jobStatusMapping;
} }
#endregion #endregion
} }
} }