Added attendanceId job details VM

This commit is contained in:
ashutosh.nehete 2025-11-17 17:43:51 +05:30
parent 64cb2e0671
commit 92a234ff7e
2 changed files with 231 additions and 0 deletions

View File

@ -16,6 +16,7 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
public DateTime StartDate { get; set; }
public DateTime DueDate { get; set; }
public bool IsActive { get; set; }
public Guid? AttendanceId { get; set; }
public TAGGING_MARK_TYPE? TaggingAction { get; set; }
public TAGGING_MARK_TYPE? NextTaggingAction { get; set; }
public DateTime CreatedAt { get; set; }

View File

@ -746,6 +746,234 @@ namespace Marco.Pms.Services.Service
#endregion
//#region =================================================================== Service Project Talking Points Functions ===================================================================
//public async Task<ApiResponse<object>> CreateTalkingPointToServiceProjectAsync(TalkingPointDto model, Employee loggedInEmployee, Guid tenantId)
//{
// var serviceProject = await _context.ServiceProjects.AsNoTracking().FirstOrDefaultAsync(sp => sp.Id == model.ServiceProjectId && sp.TenantId == tenantId);
// if (serviceProject == null)
// {
// return ApiResponse<object>.ErrorResponse("Service project not found", "Service project not found", 404);
// }
// var talkingPoint = _mapper.Map<TalkingPoint>(model);
// talkingPoint.Id = Guid.NewGuid();
// talkingPoint.IsActive = true;
// talkingPoint.CreatedAt = DateTime.UtcNow;
// talkingPoint.CreatedById = loggedInEmployee.Id;
// talkingPoint.TenantId = tenantId;
// _context.TalkingPoints.Add(talkingPoint);
// var documents = new List<Document>();
// // Handle attachments if provided
// if (model.Attachments?.Any() ?? false)
// {
// var batchId = Guid.NewGuid();
// var attachments = new List<TalkingPointAttachment>();
// foreach (var attachment in model.Attachments)
// {
// string base64 = attachment.Base64Data?.Split(',').LastOrDefault() ?? "";
// if (string.IsNullOrWhiteSpace(base64))
// {
// return ApiResponse<object>.ErrorResponse("Bad Request", "Attachment image data is missing or invalid.", 400);
// }
// // Determine content type and generate storage keys
// var fileType = _s3Service.GetContentTypeFromBase64(base64);
// var fileName = _s3Service.GenerateFileName(fileType, tenantId, "talking_point");
// var objectKey = $"tenant-{tenantId}/ServiceProject/{serviceProject.Id}/TalkingPoint/{talkingPoint.Id}/{fileName}";
// // Upload file asynchronously to S3
// await _s3Service.UploadFileAsync(base64, fileType, objectKey);
// // Create document record for uploaded file
// var document = new Document
// {
// Id = Guid.NewGuid(),
// BatchId = batchId,
// FileName = attachment.FileName ?? fileName,
// ContentType = fileType,
// S3Key = objectKey,
// FileSize = attachment.FileSize,
// UploadedAt = DateTime.UtcNow,
// UploadedById = loggedInEmployee.Id,
// TenantId = tenantId
// };
// documents.Add(document);
// // Link document as attachment to the comment
// attachments.Add(new TalkingPointAttachment
// {
// Id = Guid.NewGuid(),
// DocumentId = document.Id,
// TalkingPointId = talkingPoint.Id,
// TenantId = tenantId
// });
// }
// _context.Documents.AddRange(documents);
// _context.TalkingPointAttachments.AddRange(attachments);
// }
// var response = _mapper.Map<TalkingPointVM>(talkingPoint);
// response.ServiceProject = _mapper.Map<BasicServiceProjectVM>(serviceProject);
// response.CreatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
// if (documents.Any())
// {
// response.Attachments = documents.Select(d =>
// {
// var result = _mapper.Map<DocumentVM>(d);
// var preSignedUrl = _s3Service.GeneratePreSignedUrl(d.S3Key);
// var thumbPreSignedUrl = !string.IsNullOrWhiteSpace(d.ThumbS3Key)
// ? _s3Service.GeneratePreSignedUrl(d.ThumbS3Key)
// : preSignedUrl;
// result.PreSignedUrl = preSignedUrl;
// result.ThumbPreSignedUrl = thumbPreSignedUrl;
// return result;
// }).ToList();
// }
// return ApiResponse<object>.SuccessResponse(response, "Talking point added to service project", 201);
//}
//public async Task<ApiResponse<object>> UpdateTalkingPointAsync(Guid id, TalkingPointDto model, Employee loggedInEmployee, Guid tenantId)
//{
// // Transaction ensures atomic update of comment and attachments.
// await using var transaction = await _context.Database.BeginTransactionAsync();
// if (!model.Id.HasValue || id != model.Id)
// {
// return ApiResponse<object>.ErrorResponse("The Id in the path does not match the Id in the request body.", "The Id in the path does not match the Id in the request body.", 400);
// }
// var serviceProject = await _context.ServiceProjects.AsNoTracking().FirstOrDefaultAsync(sp => sp.Id == model.ServiceProjectId && sp.TenantId == tenantId);
// if (serviceProject == null)
// {
// return ApiResponse<object>.ErrorResponse("Service project not found", "Service project not found", 404);
// }
// var talkingPoint = await _context.TalkingPoints.AsNoTracking().FirstOrDefaultAsync(tp => tp.Id == model.Id && tp.TenantId == tenantId);
// if (talkingPoint == null)
// {
// return ApiResponse<object>.ErrorResponse("Talking point not found", "Talking point not found", 404);
// }
// _mapper.Map(model, talkingPoint);
// _context.TalkingPoints.Update(talkingPoint);
// // Attachment: Add new or remove deleted as specified in DTO
// if (model.Attachments?.Any() == true)
// {
// // New attachments
// var newBillAttachments = model.Attachments.Where(ba => ba.DocumentId == null && ba.IsActive).ToList();
// if (newBillAttachments.Any())
// {
// var batchId = Guid.NewGuid();
// var documents = new List<Document>();
// var attachments = new List<TalkingPointAttachment>();
// foreach (var attachment in newBillAttachments)
// {
// string base64 = attachment.Base64Data?.Split(',').LastOrDefault() ?? "";
// if (string.IsNullOrWhiteSpace(base64))
// {
// _logger.LogWarning("Missing base64 data for new attachment in comment {CommentId}", id);
// return ApiResponse<object>.ErrorResponse("Bad Request", "Attachment image data is missing or invalid.", 400);
// }
// // File upload and document creation
// var fileType = _s3Service.GetContentTypeFromBase64(base64);
// var fileName = _s3Service.GenerateFileName(fileType, tenantId, "job_comment");
// var objectKey = $"tenant-{tenantId}/ServiceProject/{serviceProject.Id}/TalkingPoint/{talkingPoint.Id}/{fileName}";
// await _s3Service.UploadFileAsync(base64, fileType, objectKey);
// var document = new Document
// {
// Id = Guid.NewGuid(),
// BatchId = batchId,
// FileName = attachment.FileName ?? fileName,
// ContentType = fileType,
// S3Key = objectKey,
// FileSize = attachment.FileSize,
// UploadedAt = DateTime.UtcNow,
// UploadedById = loggedInEmployee.Id,
// TenantId = tenantId
// };
// documents.Add(document);
// // Link document as attachment to the comment
// attachments.Add(new TalkingPointAttachment
// {
// Id = Guid.NewGuid(),
// DocumentId = document.Id,
// TalkingPointId = talkingPoint.Id,
// TenantId = tenantId
// });
// }
// _context.Documents.AddRange(documents);
// _context.TalkingPointAttachments.AddRange(attachments);
// try
// {
// await _context.SaveChangesAsync();
// _logger.LogInfo("{Count} new attachments added to comment {CommentId} by employee {EmployeeId}", newBillAttachments.Count, id, loggedInEmployee.Id);
// }
// catch (DbUpdateException dbEx)
// {
// await transaction.RollbackAsync();
// _logger.LogError(dbEx, "Database error adding new attachments for comment {CommentId}", id);
// return ApiResponse<object>.ErrorResponse("Database Error", dbEx.Message, 500);
// }
// }
// // Attachments for deletion
// var deleteBillAttachments = model.Attachments.Where(ba => ba.DocumentId != null && !ba.IsActive).ToList();
// if (deleteBillAttachments.Any())
// {
// var documentIds = deleteBillAttachments.Select(d => d.DocumentId!.Value).ToList();
// try
// {
// await DeleteTalkingPointAttachments(documentIds);
// _logger.LogInfo("{Count} attachments deleted for comment {CommentId} by employee {EmployeeId}", deleteBillAttachments.Count, id, loggedInEmployee.Id);
// }
// catch (DbUpdateException dbEx)
// {
// await transaction.RollbackAsync();
// _logger.LogError(dbEx, "Database error deleting attachments during comment update {CommentId}", id);
// return ApiResponse<object>.ErrorResponse("Database Error", dbEx.Message, 500);
// }
// catch (Exception ex)
// {
// await transaction.RollbackAsync();
// _logger.LogError(ex, "General error deleting attachments during comment update {CommentId}", id);
// return ApiResponse<object>.ErrorResponse("Attachment Deletion Error", ex.Message, 500);
// }
// }
// }
// var talkingPointTask = Task.Run(async () =>
// {
// await using var context = await _dbContextFactory.CreateDbContextAsync();
// return context.TalkingPoints
// .Include(tp => tp.ServiceProject)
// .Include(tp => tp.CreatedBy).ThenInclude(e => e!.JobRole)
// .Include(tp => tp.UpdatedBy).ThenInclude(e => e!.JobRole)
// .AsNoTracking()
// .FirstOrDefaultAsync(tp => tp.Id == id && tp.TenantId == tenantId && tp.IsActive);
// });
// var attachmentTask = Task.Run(async () =>
// {
// await using var context = await _dbContextFactory.CreateDbContextAsync();
// return context.TalkingPointAttachments
// .Include(tpa => tpa.Document)
// });
// return ApiResponse<object>.SuccessResponse(new { }, "Talking point updated successfully", 200);
//}
//#endregion
#region =================================================================== Job Tickets Functions ===================================================================
/// <summary>
@ -997,12 +1225,14 @@ namespace Marco.Pms.Services.Service
// 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.AttendanceId = null;
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.AttendanceId = jobAttendance.Id;
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);