802 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			802 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.Master;
 | 
						|
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 != 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 {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.Id == addCommentDto.AuthorId) ?? 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.Id == existingComment.AuthorId) ?? 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));
 | 
						|
                }
 | 
						|
                if (forumAttachmentDto.TicketId == null)
 | 
						|
                {
 | 
						|
                    _logger.LogError("ticket ID is missing");
 | 
						|
                    return BadRequest(ApiResponse<object>.ErrorResponse("ticket ID is missing", "ticket ID 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 != null ? forumAttachmentDto.TicketId.Value : Guid.Empty, 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));
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |