797 lines
42 KiB
C#
797 lines
42 KiB
C#
using Marco.Pms.DataAccess.Data;
|
|
using Marco.Pms.Model.DocumentManager;
|
|
using Marco.Pms.Model.Dtos.Forum;
|
|
using Marco.Pms.Model.Employees;
|
|
using Marco.Pms.Model.Forum;
|
|
using Marco.Pms.Model.Mapper;
|
|
using Marco.Pms.Model.Projects;
|
|
using Marco.Pms.Model.Utilities;
|
|
using Marco.Pms.Model.ViewModels.Forum;
|
|
using Marco.Pms.Services.Service;
|
|
using MarcoBMS.Services.Helpers;
|
|
using MarcoBMS.Services.Service;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Marco.Pms.Services.Controllers
|
|
{
|
|
[Authorize]
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class ForumController : ControllerBase
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
private readonly UserHelper _userHelper;
|
|
private readonly S3UploadService _s3Service;
|
|
private readonly ILoggingService _logger;
|
|
//string tenentId = "1";
|
|
public ForumController(ApplicationDbContext context, S3UploadService s3Service, UserHelper userHelper, ILoggingService logger)
|
|
{
|
|
_context = context;
|
|
_userHelper = userHelper;
|
|
_s3Service = s3Service;
|
|
_logger = logger;
|
|
}
|
|
|
|
[HttpPost("ticket")]
|
|
public async Task<IActionResult> CreateNewTicket([FromBody] CreateTicketDto createTicketDto)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
_logger.LogError("{error}", errors);
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
}
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
TicketForum ticketForum = createTicketDto.ToTicketForumFromCreateTicketDto(tenantId);
|
|
_context.Tickets.Add(ticketForum);
|
|
await _context.SaveChangesAsync();
|
|
|
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
|
List<TicketTag> ticketTags = new List<TicketTag>();
|
|
List<Document> documents = new List<Document>();
|
|
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
|
|
|
if (createTicketDto.Attachments != null)
|
|
{
|
|
foreach (var attachmentDto in createTicketDto.Attachments)
|
|
{
|
|
var Image = attachmentDto;
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
{
|
|
_logger.LogError("Base64 data is missing");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
}
|
|
|
|
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
|
|
|
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, createTicketDto.CreatedAt, tenantId);
|
|
_context.Documents.Add(document);
|
|
await _context.SaveChangesAsync();
|
|
|
|
documents.Add(document);
|
|
|
|
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(ticketForum.Id, document.Id);
|
|
attachments.Add(attachment);
|
|
}
|
|
_context.TicketAttachments.AddRange(attachments);
|
|
|
|
}
|
|
if (createTicketDto.TagIds != null)
|
|
{
|
|
List<TicketTagMaster>? tagMasters = await _context.TicketTagMasters.Where(t => createTicketDto.TagIds.Contains(t.Id)).ToListAsync();
|
|
foreach (var ticketTag in tagMasters)
|
|
{
|
|
TicketTagVM tagVM = ticketTag.ToTicketTagVMFromTicketTagMaster();
|
|
|
|
TicketTag tag = new TicketTag
|
|
{
|
|
TicketId = ticketForum.Id,
|
|
TagId = ticketTag.Id
|
|
};
|
|
tagVMs.Add(tagVM);
|
|
ticketTags.Add(tag);
|
|
}
|
|
|
|
_context.TicketTags.AddRange(ticketTags);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
|
|
var ticket = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).FirstOrDefaultAsync(t => t.Id == ticketForum.Id);
|
|
|
|
Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == ticketForum.CreatedById);
|
|
|
|
|
|
ForumTicketVM ticketVM = ticket != null && employee != null ? ticket.ToForumTicketVMFromTicketForum(employee) : new ForumTicketVM();
|
|
|
|
ticketVM.Tags = tagVMs;
|
|
|
|
List<TicketAttachmentVM> attachmentVMs = new List<TicketAttachmentVM>();
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
ticketVM.Attachments = attachmentVMs;
|
|
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticketForum.LinkedProjectId) ?? new Project();
|
|
ticketVM.ProjectName = project.Name;
|
|
if (createTicketDto.LinkedActivityId != null && createTicketDto.LinkedActivityId != null)
|
|
{
|
|
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticketForum.LinkedActivityId) ?? new WorkItem();
|
|
if (workItem.ActivityMaster != null)
|
|
{
|
|
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
|
|
}
|
|
else
|
|
{
|
|
ticketVM.ActivityName = "";
|
|
}
|
|
}
|
|
_logger.LogInfo("Ticket created by Employee {EmployeeId} for project {ProjectId}", ticketForum.CreatedById, project.Id);
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Created Successfully", 200));
|
|
}
|
|
[HttpPost("ticket/edit")]
|
|
public async Task<IActionResult> UpdateNewTicket([FromBody] UpdateTicketDto updateTicketDto)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
_logger.LogError("{error}", errors);
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
}
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
var existingTicket = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).AsNoTracking().FirstOrDefaultAsync(t => t.Id == updateTicketDto.Id);
|
|
if (existingTicket != null)
|
|
{
|
|
TicketForum ticketForum = updateTicketDto.ToTicketForumFromUpdateTicketDto(existingTicket);
|
|
_context.Tickets.Update(ticketForum);
|
|
await _context.SaveChangesAsync();
|
|
|
|
|
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
|
List<TicketTag> ticketTags = new List<TicketTag>();
|
|
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
|
|
|
List<TicketAttachment> existingAttachments = await _context.TicketAttachments.Where(a => a.TicketId == updateTicketDto.Id).ToListAsync();
|
|
var existingattachmentids = existingAttachments.Select(a => a.Id).ToList();
|
|
List<Guid> attachmentDtoids = new List<Guid>();
|
|
if (updateTicketDto.Attachments != null)
|
|
{
|
|
attachmentDtoids = updateTicketDto.Attachments.Select(a => a.Id).ToList();
|
|
foreach (var attachmentDto in updateTicketDto.Attachments)
|
|
{
|
|
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.TicketId != updateTicketDto.Id)
|
|
{
|
|
var Image = attachmentDto;
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
{
|
|
_logger.LogError("Base64 data is missing");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
}
|
|
|
|
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
|
|
|
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
|
|
_context.Documents.Add(document);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var attachment = attachmentDto.ToTicketAttachmentFromUpdateAttachmentDto(ticketForum.Id, document.Id);
|
|
attachments.Add(attachment);
|
|
}
|
|
}
|
|
}
|
|
if (attachments.Count != 0)
|
|
{
|
|
_context.TicketAttachments.AddRange(attachments);
|
|
}
|
|
var deletedAttachments = existingAttachments.Where(a => !attachmentDtoids.Contains(a.Id) && a.CommentId == null).ToList();
|
|
var deletedFileIds = deletedAttachments.Select(a => a.FileId).ToList();
|
|
if (deletedFileIds.Count != 0)
|
|
{
|
|
List<Document> existingDocuments = await _context.Documents.Where(d => deletedFileIds.Contains(d.Id)).ToListAsync();
|
|
foreach (var existingDocument in existingDocuments)
|
|
{
|
|
await _s3Service.DeleteFileAsync(existingDocument.S3Key);
|
|
//await _s3Service.DeleteFileAsync(existingDocument.ThumbS3Key);
|
|
}
|
|
_context.TicketAttachments.RemoveRange(deletedAttachments);
|
|
}
|
|
|
|
List<TicketTag> existingTicketTags = await _context.TicketTags.Where(t => t.TicketId == updateTicketDto.Id).ToListAsync();
|
|
List<TicketTagMaster>? tagMasters = await _context.TicketTagMasters.Where(t => updateTicketDto.TagIds != null ? updateTicketDto.TagIds.Contains(t.Id) : false).ToListAsync();
|
|
var existingTicketTagIds = existingTicketTags.Select(t => t.TagId).ToList();
|
|
|
|
foreach (var ticketTag in tagMasters)
|
|
{
|
|
TicketTagVM tagVM = ticketTag.ToTicketTagVMFromTicketTagMaster();
|
|
|
|
TicketTag tag = new TicketTag
|
|
{
|
|
TicketId = ticketForum.Id,
|
|
TagId = ticketTag.Id
|
|
};
|
|
tagVMs.Add(tagVM);
|
|
var demo = !existingTicketTagIds.Contains(tag.TagId);
|
|
if (!existingTicketTagIds.Contains(tag.TagId))
|
|
{
|
|
ticketTags.Add(tag);
|
|
}
|
|
}
|
|
|
|
if (ticketTags != null)
|
|
{
|
|
_context.TicketTags.AddRange(ticketTags);
|
|
}
|
|
var deletedTicketTags = existingTicketTags.Where(t => updateTicketDto.TagIds != null ? !updateTicketDto.TagIds.Contains(t.TagId) : true).ToList();
|
|
if (deletedTicketTags.Count != 0)
|
|
{
|
|
_context.TicketTags.RemoveRange(deletedTicketTags);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
|
|
var ticket = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).FirstOrDefaultAsync(t => t.Id == ticketForum.Id);
|
|
ForumTicketVM ticketVM = new ForumTicketVM();
|
|
if (ticket != null)
|
|
{
|
|
List<TicketComment> comments = await _context.TicketComments.Where(c => c.TicketId == ticket.Id).ToListAsync();
|
|
var authorIds = comments.Select(c => c.AuthorId.ToString()).ToList();
|
|
|
|
List<Employee>? employees = await _context.Employees.Where(e => e.Id == ticketForum.CreatedById || authorIds.Contains(e.ApplicationUserId ?? "")).ToListAsync();
|
|
|
|
Employee employee = employees.Find(e => e.Id == ticketForum.CreatedById) ?? new Employee();
|
|
ticketVM = ticket.ToForumTicketVMFromTicketForum(employee);
|
|
|
|
ticketVM.Tags = tagVMs;
|
|
|
|
List<TicketCommentVM> commentVMs = new List<TicketCommentVM>();
|
|
foreach (var comment in comments)
|
|
{
|
|
employee = employees.Find(e => e.ApplicationUserId == comment.AuthorId.ToString()) ?? new Employee();
|
|
commentVMs.Add(comment.ToTicketCommentVMFromTicketComment(employee));
|
|
}
|
|
|
|
attachments = await _context.TicketAttachments.Where(a => a.TicketId == updateTicketDto.Id).ToListAsync();
|
|
var fileIds = attachments.Select(a => a.FileId).ToList();
|
|
List<Document> documents = await _context.Documents.Where(d => fileIds.Contains(d.Id)).ToListAsync();
|
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
if (attachment.CommentId == null)
|
|
{
|
|
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
else
|
|
{
|
|
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
|
|
if (commentVM != null && commentVM.Attachments != null)
|
|
{
|
|
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
}
|
|
ticketVM.Comments = commentVMs;
|
|
ticketVM.Attachments = ticketAttachmentVMs;
|
|
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticketForum.LinkedProjectId) ?? new Project();
|
|
ticketVM.ProjectName = project.Name;
|
|
if (updateTicketDto.LinkedActivityId != null && updateTicketDto.LinkedActivityId != 0)
|
|
{
|
|
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticketForum.LinkedActivityId) ?? new WorkItem();
|
|
if (workItem.ActivityMaster != null)
|
|
{
|
|
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
|
|
}
|
|
else
|
|
{
|
|
ticketVM.ActivityName = "";
|
|
}
|
|
}
|
|
}
|
|
_logger.LogInfo("Ticket {TicketId} updated", updateTicketDto.Id);
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Updated Successfully", 200));
|
|
}
|
|
_logger.LogError("Ticket {TicketId} not Found in database", updateTicketDto.Id);
|
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
|
}
|
|
|
|
[HttpPost("ticket/comment")]
|
|
public async Task<IActionResult> AddComment([FromBody] AddCommentDto addCommentDto)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
_logger.LogError("{error}", errors);
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
}
|
|
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
|
List<Document> documents = new List<Document>();
|
|
|
|
TicketComment comment = addCommentDto.ToTicketCommentFromAddCommentDto(tenantId);
|
|
_context.TicketComments.Add(comment);
|
|
await _context.SaveChangesAsync();
|
|
|
|
if (addCommentDto.Attachments != null)
|
|
{
|
|
foreach (var attachmentDto in addCommentDto.Attachments)
|
|
{
|
|
var Image = attachmentDto;
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
{
|
|
_logger.LogError("Base64 data is missing");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
}
|
|
|
|
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
|
|
|
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, addCommentDto.SentAt, tenantId);
|
|
_context.Documents.Add(document);
|
|
await _context.SaveChangesAsync();
|
|
|
|
documents.Add(document);
|
|
|
|
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(addCommentDto.TicketId, document.Id, comment.Id);
|
|
attachments.Add(attachment);
|
|
}
|
|
_context.TicketAttachments.AddRange(attachments);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
Employee employee = await _context.Employees.FirstOrDefaultAsync(e => e.ApplicationUserId == addCommentDto.AuthorId.ToString()) ?? new Employee();
|
|
TicketCommentVM commentVM = comment.ToTicketCommentVMFromTicketComment(employee);
|
|
|
|
List<TicketAttachmentVM> attachmentVMs = new List<TicketAttachmentVM>();
|
|
if (attachments != null)
|
|
{
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
commentVM.Attachments = attachmentVMs;
|
|
|
|
_logger.LogInfo("User {ApplicationUserId} commented on a ticket{TicketId}", comment.AuthorId, comment.TicketId);
|
|
return Ok(ApiResponse<object>.SuccessResponse(commentVM, "Comment Created Successfully", 200));
|
|
}
|
|
[HttpPost("ticket/comment/edit")]
|
|
public async Task<IActionResult> EditComment([FromBody] UpdateCommentDto updateCommentDto)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
_logger.LogError("{error}", errors);
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
}
|
|
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
|
|
|
TicketComment existingComment = await _context.TicketComments.AsNoTracking().FirstOrDefaultAsync(c => c.Id == updateCommentDto.Id) ?? new TicketComment();
|
|
TicketComment updateComment = updateCommentDto.ToTicketCommentFromUpdateCommentDto(tenantId, existingComment);
|
|
_context.TicketComments.Update(updateComment);
|
|
await _context.SaveChangesAsync();
|
|
|
|
List<TicketAttachment> existingAttachments = await _context.TicketAttachments.Where(a => a.CommentId == updateComment.Id).ToListAsync();
|
|
var existingattachmentids = existingAttachments.Select(a => a.Id).ToList();
|
|
List<Guid> attachmentDtoids = new List<Guid>();
|
|
if (updateCommentDto.Attachments != null)
|
|
{
|
|
attachmentDtoids = updateCommentDto.Attachments.Select(a => a.Id).ToList();
|
|
|
|
foreach (var attachmentDto in updateCommentDto.Attachments)
|
|
{
|
|
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.CommentId != updateComment.Id)
|
|
{
|
|
var Image = attachmentDto;
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
{
|
|
_logger.LogError("Base64 data is missing");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
}
|
|
|
|
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
|
|
|
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
|
|
_context.Documents.Add(document);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var attachment = attachmentDto.ToTicketAttachmentFromUpdateAttachmentDto(existingComment.TicketId, document.Id, updateComment.Id);
|
|
attachments.Add(attachment);
|
|
}
|
|
}
|
|
}
|
|
if (attachments.Count != 0)
|
|
{
|
|
_context.TicketAttachments.AddRange(attachments);
|
|
}
|
|
var deletedAttachments = existingAttachments.Where(a => !attachmentDtoids.Contains(a.Id) && a.CommentId != null).ToList();
|
|
var deletedFileIds = deletedAttachments.Select(a => a.FileId).ToList();
|
|
if (deletedFileIds.Count != 0)
|
|
{
|
|
List<Document> existingDocuments = await _context.Documents.Where(d => deletedFileIds.Contains(d.Id)).ToListAsync();
|
|
foreach (var existingDocument in existingDocuments)
|
|
{
|
|
await _s3Service.DeleteFileAsync(existingDocument.S3Key);
|
|
//await _s3Service.DeleteFileAsync(existingDocument.ThumbS3Key);
|
|
}
|
|
_context.TicketAttachments.RemoveRange(deletedAttachments);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
|
|
Employee employee = await _context.Employees.FirstOrDefaultAsync(e => e.ApplicationUserId == existingComment.AuthorId.ToString()) ?? new Employee();
|
|
TicketCommentVM commentVM = updateComment.ToTicketCommentVMFromTicketComment(employee);
|
|
|
|
List<TicketAttachmentVM> attachmentVMs = new List<TicketAttachmentVM>();
|
|
attachments = await _context.TicketAttachments.Where(a => a.CommentId == updateCommentDto.Id).ToListAsync();
|
|
var fileIds = attachments.Select(a => a.FileId).ToList();
|
|
List<Document> documents = await _context.Documents.Where(d => fileIds.Contains(d.Id)).ToListAsync();
|
|
|
|
if (attachments != null)
|
|
{
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
commentVM.Attachments = attachmentVMs;
|
|
|
|
_logger.LogInfo("comment {CommentId} was Updated", updateComment.Id);
|
|
return Ok(ApiResponse<object>.SuccessResponse(commentVM, "Comment Updated Successfully", 200));
|
|
}
|
|
|
|
[HttpPost("ticket/attachment")]
|
|
public async Task<IActionResult> UploadAttachments([FromBody] List<ForumAttachmentDto> forumAttachmentDtos)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
_logger.LogError("{error}", errors);
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
}
|
|
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
|
|
|
TicketAttachment attachment = new TicketAttachment();
|
|
|
|
foreach (var forumAttachmentDto in forumAttachmentDtos)
|
|
{
|
|
if (string.IsNullOrEmpty(forumAttachmentDto.Base64Data))
|
|
{
|
|
_logger.LogError("Base64 data is missing");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
}
|
|
|
|
var objectKey = await _s3Service.UploadFileAsync(forumAttachmentDto.Base64Data, tenantId, "forum");
|
|
|
|
Document document = forumAttachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, forumAttachmentDto.SentAt, tenantId);
|
|
_context.Documents.Add(document);
|
|
await _context.SaveChangesAsync();
|
|
|
|
attachment = forumAttachmentDto.ToTicketAttachmentFromForumAttachmentDto(forumAttachmentDto.TicketId, document.Id, forumAttachmentDto.CommentId);
|
|
_context.TicketAttachments.Add(attachment);
|
|
await _context.SaveChangesAsync();
|
|
|
|
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
|
|
TicketAttachmentVM attachmentVM = attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl);
|
|
ticketAttachmentVMs.Add(attachmentVM);
|
|
}
|
|
|
|
if (attachment.CommentId == null)
|
|
{
|
|
_logger.LogInfo("Attachments were added to ticket {TicketId}", attachment.TicketId);
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInfo("Attachments were added to comment {CommentId}", attachment.CommentId);
|
|
}
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketAttachmentVMs, "attechments added Successfully", 200));
|
|
}
|
|
|
|
[HttpPatch("ticket/status/{id}")]
|
|
public async Task<IActionResult> UpdateTicketStatus(Guid id, [FromQuery] Guid statusId)
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
TicketForum ticket = await _context.Tickets.FirstOrDefaultAsync(t => t.Id == id && t.TenantId == tenantId) ?? new TicketForum();
|
|
ticket.StatusId = statusId;
|
|
await _context.SaveChangesAsync();
|
|
|
|
ticket = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).FirstOrDefaultAsync(t => t.Id == id && t.TenantId == tenantId) ?? new TicketForum();
|
|
List<TicketComment> comments = await _context.TicketComments.Where(c => c.TicketId == ticket.Id).ToListAsync();
|
|
var authorIds = comments.Select(c => c.AuthorId.ToString()).ToList();
|
|
|
|
List<Employee> employees = await _context.Employees.Where(e => e.Id == ticket.CreatedById || authorIds.Contains(e.ApplicationUserId ?? "")).ToListAsync();
|
|
Employee employee = employees.Find(e => e.Id == ticket.CreatedById) ?? new Employee();
|
|
|
|
ForumTicketVM ticketVM = ticket.ToForumTicketVMFromTicketForum(employee);
|
|
|
|
var ticketTags = await _context.TicketTags.Where(t => t.TicketId == ticket.Id).ToListAsync();
|
|
List<Guid> tagIds = ticketTags.Select(t => t.TagId).ToList();
|
|
|
|
List<TicketTagMaster>? tagMasters = await _context.TicketTagMasters.Where(t => tagIds.Contains(t.Id)).ToListAsync();
|
|
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
|
foreach (var ticketTag in tagMasters)
|
|
{
|
|
TicketTagVM tagVM = ticketTag.ToTicketTagVMFromTicketTagMaster();
|
|
tagVMs.Add(tagVM);
|
|
}
|
|
ticketVM.Tags = tagVMs;
|
|
|
|
List<TicketCommentVM> commentVMs = new List<TicketCommentVM>();
|
|
foreach (var comment in comments)
|
|
{
|
|
employee = employees.Find(e => e.ApplicationUserId == comment.AuthorId.ToString()) ?? new Employee();
|
|
commentVMs.Add(comment.ToTicketCommentVMFromTicketComment(employee));
|
|
}
|
|
|
|
List<TicketAttachment> attachments = await _context.TicketAttachments.Where(a => a.TicketId == id).ToListAsync();
|
|
List<Guid> fileIds = attachments.Select(a => a.FileId).ToList();
|
|
|
|
List<Document> documents = await _context.Documents.Where(d => fileIds.Contains(d.Id)).ToListAsync();
|
|
|
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
if (attachment.CommentId == null)
|
|
{
|
|
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
else
|
|
{
|
|
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
|
|
if (commentVM != null && commentVM.Attachments != null)
|
|
{
|
|
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
}
|
|
ticketVM.Comments = commentVMs;
|
|
ticketVM.Attachments = ticketAttachmentVMs;
|
|
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticket.LinkedProjectId) ?? new Project();
|
|
ticketVM.ProjectName = project.Name;
|
|
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != null)
|
|
{
|
|
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticket.LinkedActivityId) ?? new WorkItem();
|
|
if (workItem.ActivityMaster != null)
|
|
{
|
|
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
|
|
}
|
|
else
|
|
{
|
|
ticketVM.ActivityName = "";
|
|
}
|
|
}
|
|
_logger.LogInfo("Status of Ticket {TicketId} in project {ProjectId} is changes to {status}", id, ticket.LinkedProjectId ?? Guid.Empty, ticket.TicketStatusMaster != null ? ticket.TicketStatusMaster.Name : string.Empty);
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
|
|
}
|
|
[HttpGet("ticket/{id}")]
|
|
public async Task<IActionResult> GetTicketDetail(Guid id)
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
TicketForum ticket = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).FirstOrDefaultAsync(t => t.Id == id && t.TenantId == tenantId) ?? new TicketForum();
|
|
List<TicketComment> comments = await _context.TicketComments.Where(c => c.TicketId == ticket.Id).ToListAsync();
|
|
var authorIds = comments.Select(c => c.AuthorId.ToString()).ToList();
|
|
|
|
List<Employee> employees = await _context.Employees.Where(e => e.Id == ticket.CreatedById || authorIds.Contains(e.ApplicationUserId ?? "")).ToListAsync();
|
|
Employee employee = employees.Find(e => e.Id == ticket.CreatedById) ?? new Employee();
|
|
|
|
ForumTicketVM ticketVM = ticket.ToForumTicketVMFromTicketForum(employee);
|
|
|
|
var ticketTags = await _context.TicketTags.Where(t => t.TicketId == ticket.Id).ToListAsync();
|
|
List<Guid> tagIds = ticketTags.Select(t => t.TagId).ToList();
|
|
|
|
List<TicketTagMaster>? tagMasters = await _context.TicketTagMasters.Where(t => tagIds.Contains(t.Id)).ToListAsync();
|
|
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
|
foreach (var ticketTag in tagMasters)
|
|
{
|
|
TicketTagVM tagVM = ticketTag.ToTicketTagVMFromTicketTagMaster();
|
|
tagVMs.Add(tagVM);
|
|
}
|
|
ticketVM.Tags = tagVMs;
|
|
|
|
List<TicketCommentVM> commentVMs = new List<TicketCommentVM>();
|
|
foreach (var comment in comments)
|
|
{
|
|
employee = employees.Find(e => e.ApplicationUserId == comment.AuthorId.ToString()) ?? new Employee();
|
|
commentVMs.Add(comment.ToTicketCommentVMFromTicketComment(employee));
|
|
}
|
|
|
|
List<TicketAttachment> attachments = await _context.TicketAttachments.Where(a => a.TicketId == id).ToListAsync();
|
|
List<Guid> fileIds = attachments.Select(a => a.FileId).ToList();
|
|
|
|
List<Document> documents = await _context.Documents.Where(d => fileIds.Contains(d.Id)).ToListAsync();
|
|
|
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
if (attachment.CommentId == null)
|
|
{
|
|
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
else
|
|
{
|
|
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
|
|
if (commentVM != null && commentVM.Attachments != null)
|
|
{
|
|
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
}
|
|
ticketVM.Comments = commentVMs;
|
|
ticketVM.Attachments = ticketAttachmentVMs;
|
|
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticket.LinkedProjectId) ?? new Project();
|
|
ticketVM.ProjectName = project.Name;
|
|
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != null)
|
|
{
|
|
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticket.LinkedActivityId) ?? new WorkItem();
|
|
if (workItem.ActivityMaster != null)
|
|
{
|
|
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
|
|
}
|
|
else
|
|
{
|
|
ticketVM.ActivityName = "";
|
|
}
|
|
}
|
|
_logger.LogInfo("Fetched Ticket {TicketId} form project {ProjectId}", id, ticket.LinkedProjectId ?? Guid.Empty);
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
|
|
}
|
|
|
|
[HttpGet("tickets")]
|
|
public async Task<IActionResult> ListTickets()
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
List<TicketForum> tickets = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).Where(t => t.TenantId == tenantId).ToListAsync();
|
|
var createdByIds = tickets.Select(t => t.CreatedById).ToList();
|
|
var ticketIds = tickets.Select(t => t.Id).ToList();
|
|
var linkedActivityIds = tickets.Select(t => t.LinkedActivityId).ToList();
|
|
var linkedProjectIds = tickets.Select(t => t.LinkedProjectId).ToList();
|
|
|
|
List<TicketComment> ticketComments = await _context.TicketComments.Where(c => ticketIds.Contains(c.TicketId)).ToListAsync();
|
|
var authorIds = ticketComments.Select(c => c.AuthorId.ToString()).ToList();
|
|
|
|
List<Employee> employees = await _context.Employees.Where(e => createdByIds.Contains(e.Id) || (e.ApplicationUserId != null && authorIds.Contains(e.ApplicationUserId))).ToListAsync();
|
|
|
|
var ticketTags = await _context.TicketTags.Where(t => ticketIds.Contains(t.TicketId)).ToListAsync();
|
|
List<Guid> tagIds = ticketTags.Select(t => t.TagId).ToList();
|
|
|
|
List<TicketTagMaster>? tagMasters = await _context.TicketTagMasters.Where(t => tagIds.Contains(t.Id)).ToListAsync();
|
|
|
|
List<TicketAttachment> ticketAttachments = await _context.TicketAttachments.Where(a => ticketIds.Contains(a.TicketId)).ToListAsync();
|
|
List<Guid> documentIds = ticketAttachments.Select(a => a.FileId).ToList();
|
|
|
|
List<Document> documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync();
|
|
|
|
List<Project> projects = await _context.Projects.Where(p => linkedProjectIds.Contains(p.Id)).ToListAsync() ?? new List<Project>();
|
|
|
|
List<WorkItem> workItems = await _context.WorkItems.Include(w => w.ActivityMaster).Where(w => linkedActivityIds.Contains(w.Id)).ToListAsync() ?? new List<WorkItem>();
|
|
|
|
List<ForumTicketVM> ticketVMs = new List<ForumTicketVM>();
|
|
foreach (var ticket in tickets)
|
|
{
|
|
Employee employee = employees.Find(e => e.Id == ticket.CreatedById) ?? new Employee();
|
|
ForumTicketVM ticketVM = ticket.ToForumTicketVMFromTicketForum(employee);
|
|
|
|
var ticketTagMappers = ticketTags.Where(t => t.TicketId == ticket.Id).ToList();
|
|
List<Guid> ticketTagIds = ticketTagMappers.Select(t => t.TagId).ToList();
|
|
|
|
List<TicketTagMaster> ticketTagMasters = tagMasters.Where(t => ticketTagIds.Contains(t.Id)).ToList();
|
|
|
|
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
|
foreach (var ticketTag in ticketTagMasters)
|
|
{
|
|
TicketTagVM tagVM = ticketTag.ToTicketTagVMFromTicketTagMaster();
|
|
tagVMs.Add(tagVM);
|
|
}
|
|
|
|
List<TicketComment> comments = ticketComments.Where(c => c.TicketId == ticket.Id).ToList();
|
|
List<TicketCommentVM> commentVMs = new List<TicketCommentVM>();
|
|
foreach (var comment in comments)
|
|
{
|
|
employee = employees.Find(e => e.ApplicationUserId == comment.AuthorId.ToString()) ?? new Employee();
|
|
commentVMs.Add(comment.ToTicketCommentVMFromTicketComment(employee));
|
|
}
|
|
|
|
List<TicketAttachment> attachments = ticketAttachments.Where(a => a.TicketId == ticket.Id).ToList();
|
|
List<Guid> fileIds = attachments.Select(a => a.FileId).ToList();
|
|
|
|
List<Document> files = documents.Where(d => fileIds.Contains(d.Id)).ToList();
|
|
|
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
|
foreach (var attachment in attachments)
|
|
{
|
|
var document = documents.Find(d => d.Id == attachment.FileId);
|
|
string preSignedUrl = string.Empty;
|
|
if (document != null)
|
|
{
|
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
}
|
|
if (attachment.CommentId == null)
|
|
{
|
|
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
else
|
|
{
|
|
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
|
|
if (commentVM != null && commentVM.Attachments != null)
|
|
{
|
|
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
|
|
}
|
|
}
|
|
}
|
|
ticketVM.Comments = commentVMs;
|
|
ticketVM.Attachments = ticketAttachmentVMs;
|
|
ticketVM.Tags = tagVMs;
|
|
Project project = projects.Find(p => p.Id == ticket.LinkedProjectId) ?? new Project();
|
|
ticketVM.ProjectName = project.Name;
|
|
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != null)
|
|
{
|
|
WorkItem workItem = workItems.Find(w => w.Id == ticket.LinkedActivityId) ?? new WorkItem();
|
|
if (workItem.ActivityMaster != null)
|
|
{
|
|
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
|
|
}
|
|
else
|
|
{
|
|
ticketVM.ActivityName = "";
|
|
}
|
|
}
|
|
ticketVMs.Add(ticketVM);
|
|
}
|
|
_logger.LogInfo("{count} tickets records fetched successfully from tenant {tenantId}", ticketVMs.Count, tenantId);
|
|
return Ok(ApiResponse<object>.SuccessResponse(ticketVMs, System.String.Format("{0} tickets records fetched successfully", ticketVMs.Count), 200));
|
|
}
|
|
}
|
|
}
|