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.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));
}
int tenantId = _userHelper.GetTenantId();
if (tenantId == createTicketDto.TenantId)
{
TicketForum ticketForum = createTicketDto.ToTicketForumFromCreateTicketDto();
_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)
{
byte[] fileBytes;
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));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
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.ToForumTicketVMFromTicketForum(employee);
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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
ticketVM.Attachments = attachmentVMs;
_logger.LogInfo("Ticket created by Employee {EmployeeId}", ticketForum.CreatedById);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Created Successfully", 200));
}
_logger.LogWarning("Employee {EmployeeId} tries to create ticket in different Tenant", createTicketDto.CreatedById);
return Unauthorized(ApiResponse<object>.ErrorResponse("Not Authorized", "Not Authorized", 401));
}
[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));
}
int tenantId = _userHelper.GetTenantId();
if (tenantId == updateTicketDto.TenantId)
{
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();
var attachmentDtoids = updateTicketDto.Attachments.Select(a => a.Id).ToList();
foreach (var attachmentDto in updateTicketDto.Attachments)
{
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.TicketId != updateTicketDto.Id)
{
byte[] fileBytes;
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));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(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.Contains(t.Id)).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.Contains(t.TagId)).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);
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);
ForumTicketVM 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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
else
{
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
}
ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs;
_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));
}
_logger.LogWarning("Employee {EmployeeId} tries to create ticket in different Tenant", updateTicketDto.CreatedById);
return Unauthorized(ApiResponse<object>.ErrorResponse("Not Authorized", "Not Authorized", 401));
}
[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));
}
int tenantId = _userHelper.GetTenantId();
List<TicketAttachment> attachments = new List<TicketAttachment>();
List<Document> documents = new List<Document>();
TicketComment comment = addCommentDto.ToTicketCommentFromAddCommentDto();
_context.TicketComments.Add(comment);
await _context.SaveChangesAsync();
if (addCommentDto.Attachments != null)
{
foreach (var attachmentDto in addCommentDto.Attachments)
{
byte[] fileBytes;
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));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
}
commentVM.Attachments = attachmentVMs;
_logger.LogInfo("User {ApplicationUserId} commented on a ticket", comment.AuthorId);
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));
}
int 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();
var attachmentDtoids = updateCommentDto.Attachments.Select(a => a.Id).ToList();
foreach (var attachmentDto in updateCommentDto.Attachments)
{
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.CommentId != updateComment.Id)
{
byte[] fileBytes;
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));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(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 = await _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));
}
int tenantId = _userHelper.GetTenantId();
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
foreach (var forumAttachmentDto in forumAttachmentDtos)
{
byte[] fileBytes;
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));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = forumAttachmentDto.Base64Data.Contains(",")
? forumAttachmentDto.Base64Data.Substring(forumAttachmentDto.Base64Data.IndexOf(",") + 1)
: forumAttachmentDto.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(forumAttachmentDto.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, forumAttachmentDto.ContentType);
Document document = forumAttachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, forumAttachmentDto.SentAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = forumAttachmentDto.ToTicketAttachmentFromForumAttachmentDto(forumAttachmentDto.TicketId, document.Id, forumAttachmentDto.CommentId);
_context.TicketAttachments.Add(attachment);
await _context.SaveChangesAsync();
string preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
TicketAttachmentVM attachmentVM = attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl);
ticketAttachmentVMs.Add(attachmentVM);
}
_logger.LogInfo("Attachments were added");
return Ok(ApiResponse<object>.SuccessResponse(ticketAttachmentVMs, "attechments added Successfully", 200));
}
[HttpPatch("ticket/status/{id}")]
public async Task<IActionResult> UpdateTicketStatus(Guid id, [FromQuery] Guid statusId)
{
int 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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
else
{
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
}
ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs;
_logger.LogInfo("Status of Ticket {TicketId} is changes to {status}", id, ticket.TicketStatusMaster.Name);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
}
[HttpGet("ticket/{id}")]
public async Task<IActionResult> GetTicketDetail(Guid id)
{
int 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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
else
{
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
}
ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs;
_logger.LogInfo("Fetched Ticket {TicketId}", id);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
}
[HttpGet("tickets")]
public async Task<IActionResult> ListTickets()
{
int 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();
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) || 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<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 = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
ticketAttachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
else
{
var commentVM = commentVMs.Find(c => c.Id == attachment.CommentId);
commentVM.Attachments.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
}
ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs;
ticketVM.Tags = tagVMs;
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));
}
}
}