Added the Attachments in job comments APIs and removed list of comments from job tickets details API
This commit is contained in:
parent
611d7753bb
commit
2f04339b4d
@ -1,8 +1,11 @@
|
||||
namespace Marco.Pms.Model.Dtos.ServiceProject
|
||||
using Marco.Pms.Model.Utilities;
|
||||
|
||||
namespace Marco.Pms.Model.Dtos.ServiceProject
|
||||
{
|
||||
public class JobCommentDto
|
||||
{
|
||||
public required Guid JobTicketId { get; set; }
|
||||
public required string Comment { get; set; }
|
||||
public List<FileUploadModel>? Attachments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,6 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public BasicEmployeeVM? UpdatedBy { get; set; }
|
||||
public List<DocumentVM>? Documents { get; set; }
|
||||
public List<DocumentVM>? Attachments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,5 @@ namespace Marco.Pms.Model.ViewModels.ServiceProject
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public List<TagVM>? Tags { get; set; }
|
||||
public List<JobUpdateLogVM>? UpdateLogs { get; set; }
|
||||
public List<JobCommentVM>? Comments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,6 +499,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
|
||||
#region ======================================================= Document =======================================================
|
||||
|
||||
CreateMap<Document, DocumentVM>();
|
||||
CreateMap<DocumentMongoDB, BasicDocumentVM>()
|
||||
.ForMember(
|
||||
dest => dest.DocumentId,
|
||||
|
||||
@ -67,11 +67,7 @@ namespace Marco.Pms.Services.Service
|
||||
/// <param name="loggedInEmployee">Employee requesting the statuses.</param>
|
||||
/// <param name="tenantId">Tenant identifier for multi-tenant scope.</param>
|
||||
/// <returns>ApiResponse containing list of job statuses or error details.</returns>
|
||||
public async Task<ApiResponse<object>> GetJobStatusAsync(
|
||||
Guid? statusId,
|
||||
Guid? projectId,
|
||||
Employee loggedInEmployee,
|
||||
Guid tenantId)
|
||||
public async Task<ApiResponse<object>> GetJobStatusAsync(Guid? statusId, Guid? projectId, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogDebug("GetJobStatusAsync called by employee {EmployeeId} in tenant {TenantId}", loggedInEmployee.Id, tenantId);
|
||||
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
using AutoMapper;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.ServiceProject;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.ServiceProject;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.DocumentManager;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Model.ViewModels.Organization;
|
||||
using Marco.Pms.Model.ViewModels.ServiceProject;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -23,7 +24,7 @@ namespace Marco.Pms.Services.Service
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly CacheUpdateHelper _cache;
|
||||
private readonly S3UploadService _s3Service;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly Guid NewStatus = Guid.Parse("32d76a02-8f44-4aa0-9b66-c3716c45a918");
|
||||
@ -33,13 +34,13 @@ namespace Marco.Pms.Services.Service
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
ApplicationDbContext context,
|
||||
ILoggingService logger,
|
||||
CacheUpdateHelper cache,
|
||||
S3UploadService s3Service,
|
||||
IMapper mapper)
|
||||
{
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
_cache = cache;
|
||||
_s3Service = s3Service;
|
||||
_mapper = mapper;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
@ -560,15 +561,6 @@ namespace Marco.Pms.Services.Service
|
||||
.ToListAsync();
|
||||
});
|
||||
|
||||
var commentTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.JobComments
|
||||
.Include(jc => jc.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(jc => jc.JobTicketId == id && jc.TenantId == tenantId)
|
||||
.ToListAsync();
|
||||
});
|
||||
|
||||
var updateLogTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
@ -578,7 +570,7 @@ namespace Marco.Pms.Services.Service
|
||||
.ToListAsync();
|
||||
});
|
||||
|
||||
await Task.WhenAll(assigneeTask, tagTask, commentTask, updateLogTask);
|
||||
await Task.WhenAll(assigneeTask, tagTask, updateLogTask);
|
||||
|
||||
// Map update logs with status descriptions
|
||||
var jobUpdateLogVMs = updateLogTask.Result.Select(ul =>
|
||||
@ -595,13 +587,7 @@ namespace Marco.Pms.Services.Service
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
// Map comments, assignees, and tags to their respective viewmodels
|
||||
var commentVMs = _mapper.Map<List<JobCommentVM>>(commentTask.Result);
|
||||
commentVMs = commentVMs.Select(vm =>
|
||||
{
|
||||
vm.JobTicket = _mapper.Map<BasicJobTicketVM>(jobTicket);
|
||||
return vm;
|
||||
}).ToList();
|
||||
// Map assignees, and tags to their respective viewmodels
|
||||
var assigneeVMs = _mapper.Map<List<BasicEmployeeVM>>(assigneeTask.Result);
|
||||
var tagVMs = _mapper.Map<List<TagVM>>(tagTask.Result);
|
||||
|
||||
@ -610,7 +596,6 @@ namespace Marco.Pms.Services.Service
|
||||
response.Assignees = assigneeVMs;
|
||||
response.Tags = tagVMs;
|
||||
response.UpdateLogs = jobUpdateLogVMs;
|
||||
response.Comments = commentVMs;
|
||||
|
||||
_logger.LogInfo("Job ticket details assembled successfully for JobTicketId: {JobTicketId}", id);
|
||||
|
||||
@ -623,91 +608,6 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a paginated list of comments for a specified job ticket within a tenant context.
|
||||
/// </summary>
|
||||
/// <param name="jobTicketId">Optional job ticket identifier to filter comments.</param>
|
||||
/// <param name="pageNumber">Page number (1-based index) for pagination.</param>
|
||||
/// <param name="pageSize">Page size for pagination.</param>
|
||||
/// <param name="loggedInEmployee">Employee making the request (for logging).</param>
|
||||
/// <param name="tenantId">Tenant context to scope data.</param>
|
||||
/// <returns>ApiResponse with paged comment view models or error details.</returns>
|
||||
public async Task<ApiResponse<object>> GetCommentListByJobTicketAsync(Guid? jobTicketId, int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
if (tenantId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning("TenantId missing in comment list request by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "Invalid tenant context.", 403);
|
||||
}
|
||||
|
||||
if (pageNumber < 1 || pageSize < 1)
|
||||
{
|
||||
_logger.LogInfo("Invalid pagination parameters in comment list request. PageNumber: {PageNumber}, PageSize: {PageSize}", pageNumber, pageSize);
|
||||
return ApiResponse<object>.ErrorResponse("Bad Request", "Page number and size must be greater than zero.", 400);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInfo("Fetching comment list for jobTicketId {JobTicketId} by employee {EmployeeId} in tenant {TenantId}",
|
||||
jobTicketId ?? Guid.Empty, loggedInEmployee.Id, tenantId);
|
||||
|
||||
var commentQuery = _context.JobComments
|
||||
.Include(jc => jc.JobTicket).ThenInclude(jt => jt!.Status)
|
||||
.Include(jc => jc.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(jc =>
|
||||
jc.TenantId == tenantId &&
|
||||
jc.JobTicket != null &&
|
||||
jc.CreatedBy != null &&
|
||||
jc.CreatedBy.JobRole != null);
|
||||
|
||||
// Validate and filter by job ticket if specified
|
||||
if (jobTicketId.HasValue)
|
||||
{
|
||||
var jobTicketExists = await _context.JobTickets.AnyAsync(jt =>
|
||||
jt.Id == jobTicketId && jt.TenantId == tenantId);
|
||||
|
||||
if (!jobTicketExists)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found in tenant {TenantId} for comment listing", jobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job ticket not found.", 404);
|
||||
}
|
||||
|
||||
commentQuery = commentQuery.Where(jc => jc.JobTicketId == jobTicketId.Value);
|
||||
}
|
||||
|
||||
var totalEntities = await commentQuery.CountAsync();
|
||||
var totalPages = (int)Math.Ceiling((double)totalEntities / pageSize);
|
||||
|
||||
var comments = await commentQuery
|
||||
.OrderByDescending(jc => jc.CreatedAt)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
var commentVMs = _mapper.Map<List<JobCommentVM>>(comments);
|
||||
|
||||
var response = new
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
TotalPages = totalPages,
|
||||
TotalEntities = totalEntities,
|
||||
Data = commentVMs,
|
||||
};
|
||||
|
||||
_logger.LogInfo("{Count} comments fetched successfully for jobTicketId {JobTicketId} by employee {EmployeeId}",
|
||||
commentVMs.Count, jobTicketId ?? Guid.Empty, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, $"{commentVMs.Count} record(s) fetched successfully.", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching comments for jobTicketId {JobTicketId} by employee {EmployeeId} in tenant {TenantId}",
|
||||
jobTicketId ?? Guid.Empty, loggedInEmployee.Id, tenantId);
|
||||
|
||||
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Failed to fetch comments. Please try again later.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all job tags associated with the tenant, ordered alphabetically by name.
|
||||
/// </summary>
|
||||
@ -928,21 +828,145 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region =================================================================== Job Comments Functions ===================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new comment to an existing job ticket within the tenant context.
|
||||
/// Retrieves a paginated list of comments with attachments for a specified job ticket within a tenant context.
|
||||
/// </summary>
|
||||
/// <param name="model">Comment data transfer object containing the job ticket ID and comment text.</param>
|
||||
/// <param name="loggedInEmployee">Employee adding the comment (for auditing).</param>
|
||||
/// <param name="tenantId">Tenant identifier to enforce multi-tenancy.</param>
|
||||
/// <returns>ApiResponse with the created comment view or error details.</returns>
|
||||
/// <param name="jobTicketId">Optional job ticket ID to filter comments.</param>
|
||||
/// <param name="pageNumber">Page number (1-based) for pagination.</param>
|
||||
/// <param name="pageSize">Page size for pagination.</param>
|
||||
/// <param name="loggedInEmployee">Employee making the request (for authorization and logging).</param>
|
||||
/// <param name="tenantId">Tenant context ID for multi-tenancy.</param>
|
||||
/// <returns>ApiResponse with paged comments, attachments, and metadata, or error details.</returns>
|
||||
public async Task<ApiResponse<object>> GetCommentListByJobTicketAsync(Guid? jobTicketId, int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
if (tenantId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning("TenantId missing in comment list request by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "Invalid tenant context.", 403);
|
||||
}
|
||||
|
||||
if (pageNumber < 1 || pageSize < 1)
|
||||
{
|
||||
_logger.LogInfo("Invalid pagination parameters in comment list request. PageNumber: {PageNumber}, PageSize: {PageSize}", pageNumber, pageSize);
|
||||
return ApiResponse<object>.ErrorResponse("Bad Request", "Page number and size must be greater than zero.", 400);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInfo("Fetching comment list for jobTicketId {JobTicketId} by employee {EmployeeId} in tenant {TenantId}",
|
||||
jobTicketId ?? Guid.Empty, loggedInEmployee.Id, tenantId);
|
||||
|
||||
var commentQuery = _context.JobComments
|
||||
.Include(jc => jc.JobTicket).ThenInclude(jt => jt!.Status)
|
||||
.Include(jc => jc.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Include(jc => jc.UpdatedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(jc => jc.TenantId == tenantId && jc.JobTicket != null && jc.CreatedBy != null && jc.CreatedBy.JobRole != null);
|
||||
|
||||
// Filter by jobTicketId if provided after verifying existence
|
||||
if (jobTicketId.HasValue)
|
||||
{
|
||||
var jobTicketExists = await _context.JobTickets.AnyAsync(jt =>
|
||||
jt.Id == jobTicketId && jt.TenantId == tenantId);
|
||||
|
||||
if (!jobTicketExists)
|
||||
{
|
||||
_logger.LogWarning("Job ticket {JobTicketId} not found in tenant {TenantId} for comment listing", jobTicketId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Job not found", "Job ticket not found.", 404);
|
||||
}
|
||||
|
||||
commentQuery = commentQuery.Where(jc => jc.JobTicketId == jobTicketId.Value);
|
||||
}
|
||||
|
||||
// Calculate total count for pagination
|
||||
var totalEntities = await commentQuery.CountAsync();
|
||||
var totalPages = (int)Math.Ceiling((double)totalEntities / pageSize);
|
||||
|
||||
// Fetch paged comments ordered by creation date descending
|
||||
var comments = await commentQuery
|
||||
.OrderByDescending(jc => jc.CreatedAt)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
var commentIds = comments.Select(jc => jc.Id).ToList();
|
||||
|
||||
// Fetch attachments for current page comments
|
||||
var attachments = await _context.JobAttachments
|
||||
.Include(ja => ja.Document)
|
||||
.Where(ja => ja.JobCommentId.HasValue &&
|
||||
ja.Document != null &&
|
||||
commentIds.Contains(ja.JobCommentId.Value) &&
|
||||
ja.TenantId == tenantId)
|
||||
.ToListAsync();
|
||||
|
||||
// Map comments and attach corresponding documents with pre-signed URLs for access
|
||||
var commentVMs = comments.Select(jc =>
|
||||
{
|
||||
var relatedDocuments = attachments
|
||||
.Where(ja => ja.JobCommentId == jc.Id)
|
||||
.Select(ja => ja.Document!)
|
||||
.ToList();
|
||||
|
||||
var mappedComment = _mapper.Map<JobCommentVM>(jc);
|
||||
|
||||
if (relatedDocuments.Any())
|
||||
{
|
||||
mappedComment.Attachments = relatedDocuments.Select(doc =>
|
||||
{
|
||||
var docVM = _mapper.Map<DocumentVM>(doc);
|
||||
docVM.PreSignedUrl = _s3Service.GeneratePreSignedUrl(doc.S3Key);
|
||||
docVM.ThumbPreSignedUrl = string.IsNullOrWhiteSpace(doc.ThumbS3Key) ?
|
||||
_s3Service.GeneratePreSignedUrl(doc.S3Key) :
|
||||
_s3Service.GeneratePreSignedUrl(doc.ThumbS3Key);
|
||||
return docVM;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return mappedComment;
|
||||
}).ToList();
|
||||
|
||||
var response = new
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
TotalPages = totalPages,
|
||||
TotalEntities = totalEntities,
|
||||
Data = commentVMs
|
||||
};
|
||||
|
||||
_logger.LogInfo("{Count} comments fetched successfully for jobTicketId {JobTicketId} by employee {EmployeeId}",
|
||||
commentVMs.Count, jobTicketId ?? Guid.Empty, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, $"{commentVMs.Count} record(s) fetched successfully.", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching comments for jobTicketId {JobTicketId} by employee {EmployeeId} in tenant {TenantId}",
|
||||
jobTicketId ?? Guid.Empty, loggedInEmployee.Id, tenantId);
|
||||
|
||||
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Failed to fetch comments. Please try again later.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a comment with optional attachments to a job ticket within the specified tenant context.
|
||||
/// </summary>
|
||||
/// <param name="model">DTO containing comment content, job ticket ID, and attachments.</param>
|
||||
/// <param name="loggedInEmployee">Employee making the comment (for auditing).</param>
|
||||
/// <param name="tenantId">Tenant context for data isolation.</param>
|
||||
/// <returns>ApiResponse containing created comment details or relevant error information.</returns>
|
||||
public async Task<ApiResponse<object>> AddCommentToJobTicketAsync(JobCommentDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
// Validate tenant context
|
||||
if (tenantId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning("Add comment attempt with invalid tenant context by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "Invalid tenant context.", 403);
|
||||
}
|
||||
|
||||
// Validate input DTO
|
||||
if (model == null || model.JobTicketId == Guid.Empty || string.IsNullOrWhiteSpace(model.Comment))
|
||||
{
|
||||
_logger.LogInfo("Invalid comment model provided by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
@ -953,7 +977,7 @@ namespace Marco.Pms.Services.Service
|
||||
{
|
||||
_logger.LogInfo("Attempting to add comment to job ticket {JobTicketId} by employee {EmployeeId}", model.JobTicketId, loggedInEmployee.Id);
|
||||
|
||||
// Verify if the job ticket exists within tenant and load status for response mapping
|
||||
// Verify the job ticket's existence and load minimal required info
|
||||
var jobTicket = await _context.JobTickets
|
||||
.Include(jt => jt.Status)
|
||||
.AsNoTracking()
|
||||
@ -965,22 +989,78 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<object>.ErrorResponse("Job Not Found", "Job ticket not found or inaccessible.", 404);
|
||||
}
|
||||
|
||||
// Create and save new comment entity
|
||||
// Create new comment entity
|
||||
var comment = new JobComment
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
JobTicketId = jobTicket.Id,
|
||||
Comment = model.Comment.Trim(),
|
||||
IsActive = true,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
CreatedById = loggedInEmployee.Id,
|
||||
TenantId = tenantId
|
||||
};
|
||||
|
||||
_context.JobComments.Add(comment);
|
||||
|
||||
// Handle attachments if provided
|
||||
if (model.Attachments?.Any() ?? false)
|
||||
{
|
||||
var batchId = Guid.NewGuid();
|
||||
var documents = new List<Document>();
|
||||
var attachments = new List<JobAttachment>();
|
||||
|
||||
foreach (var attachment in model.Attachments)
|
||||
{
|
||||
string base64 = attachment.Base64Data?.Split(',').LastOrDefault() ?? "";
|
||||
if (string.IsNullOrWhiteSpace(base64))
|
||||
{
|
||||
_logger.LogWarning("Attachment missing base64 data in comment for job ticket {JobTicketId} by employee {EmployeeId}", jobTicket.Id, loggedInEmployee.Id);
|
||||
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, "job");
|
||||
var objectKey = $"tenant-{tenantId}/ServiceProject/{jobTicket.ProjectId}/Job/{jobTicket.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 JobAttachment
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
DocumentId = document.Id,
|
||||
StatusId = jobTicket.StatusId,
|
||||
JobCommentId = comment.Id,
|
||||
TenantId = tenantId
|
||||
});
|
||||
}
|
||||
_context.Documents.AddRange(documents);
|
||||
_context.JobAttachments.AddRange(attachments);
|
||||
}
|
||||
|
||||
// Persist all inserts in database
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Map response including basic job ticket info
|
||||
// Prepare response with mapped comment, creator info, and basic job ticket info
|
||||
var response = _mapper.Map<JobCommentVM>(comment);
|
||||
response.CreatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
|
||||
response.JobTicket = _mapper.Map<BasicJobTicketVM>(jobTicket);
|
||||
|
||||
_logger.LogInfo("Successfully added comment {CommentId} to job ticket {JobTicketId} by employee {EmployeeId}",
|
||||
@ -996,7 +1076,6 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user