Added attendanceId job details VM
This commit is contained in:
parent
64cb2e0671
commit
92a234ff7e
@ -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; }
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user