Added the an API to add comment to the job ticket

This commit is contained in:
ashutosh.nehete 2025-11-13 13:03:31 +05:30
parent 4401bc0fa2
commit 6679c5877d
5 changed files with 92 additions and 2 deletions

View File

@ -0,0 +1,8 @@
namespace Marco.Pms.Model.Dtos.ServiceProject
{
public class JobCommentDto
{
public required Guid JobTicketId { get; set; }
public required string Comment { get; set; }
}
}

View File

@ -123,6 +123,19 @@ namespace Marco.Pms.Services.Controllers
}
return StatusCode(response.StatusCode, response);
}
[HttpPost("job/add/comment")]
public async Task<IActionResult> AddCommentToJobTicket(JobCommentDto model)
{
Employee loggedInEmploee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _serviceProject.AddCommentToJobTicketAsync(model, loggedInEmploee, tenantId);
if (response.Success)
{
var notification = new { LoggedInUserId = loggedInEmploee.Id, Keyword = "Job_Ticket_Comment", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
#endregion
}
}

View File

@ -207,6 +207,8 @@ namespace Marco.Pms.Services.MappingProfiles
dest => dest.StatusName,
opt => opt.MapFrom(src => src.Status != null ? src.Status.Name : null));
CreateMap<JobComment, JobCommentVM>();
#endregion
#endregion

View File

@ -19,6 +19,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> GetJobTicketsListAsync(Guid? projectId, int pageNumber, int pageSize, bool isActive, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetJobTicketDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateJobTicketAsync(CreateJobTicketDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> AddCommentToJobTicketAsync(JobCommentDto model, Employee loggedInEmployee, Guid tenantId);
#endregion
}

View File

@ -618,8 +618,6 @@ namespace Marco.Pms.Services.Service
}
}
/// <summary>
/// Creates a new job ticket with optional assignees and tags within a transactional scope.
/// </summary>
@ -798,6 +796,74 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Internal Server Error", "An unexpected error occurred.", 500);
}
}
/// <summary>
/// Adds a new comment to an existing job ticket within the 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>
public async Task<ApiResponse<object>> AddCommentToJobTicketAsync(JobCommentDto model, Employee loggedInEmployee, Guid tenantId)
{
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);
}
if (model == null || model.JobTicketId == Guid.Empty || string.IsNullOrWhiteSpace(model.Comment))
{
_logger.LogInfo("Invalid comment model provided by employee {EmployeeId}", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Bad Request", "Comment data is incomplete or invalid.", 400);
}
try
{
_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
var jobTicket = await _context.JobTickets
.Include(jt => jt.Status)
.AsNoTracking()
.FirstOrDefaultAsync(jt => jt.Id == model.JobTicketId && jt.TenantId == tenantId);
if (jobTicket == null)
{
_logger.LogWarning("Job ticket {JobTicketId} not found or inaccessible in tenant {TenantId}", model.JobTicketId, tenantId);
return ApiResponse<object>.ErrorResponse("Job Not Found", "Job ticket not found or inaccessible.", 404);
}
// Create and save new comment entity
var comment = new JobComment
{
Id = Guid.NewGuid(),
JobTicketId = jobTicket.Id,
Comment = model.Comment.Trim(),
CreatedAt = DateTime.UtcNow,
CreatedById = loggedInEmployee.Id,
TenantId = tenantId
};
_context.JobComments.Add(comment);
await _context.SaveChangesAsync();
// Map response including basic job ticket info
var response = _mapper.Map<JobCommentVM>(comment);
response.JobTicket = _mapper.Map<BasicJobTicketVM>(jobTicket);
_logger.LogInfo("Successfully added comment {CommentId} to job ticket {JobTicketId} by employee {EmployeeId}",
comment.Id, jobTicket.Id, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, "Comment added to job ticket successfully.", 201);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding comment to job ticket {JobTicketId} by employee {EmployeeId} in tenant {TenantId}",
model.JobTicketId, loggedInEmployee.Id, tenantId);
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Failed to add comment. Please try again later.", 500);
}
}
#endregion
}