Implemented core forum features including ticket creation, ticket updates, adding and updating comments, managing attachments, retrieving ticket details by ID, and fetching the ticket list
This commit is contained in:
parent
fce124ac8b
commit
ace2fe7d54
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
{
|
||||
public class AddCommentDto
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public Guid TicketId { get; set; } = Guid.Empty;
|
||||
public Guid AuthorId { get; set; }
|
||||
public string MessageText { get; set; } = string.Empty;
|
||||
public DateTime SentAt { get; set; }
|
||||
public Guid? ParentMessageId { get; set; } // For threaded replies
|
||||
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,17 @@
|
||||
{
|
||||
public class CreateTicketDto
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public Guid StatusId { get; set; }
|
||||
public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback
|
||||
public int CreatedById { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public int LinkedActivityId { get; set; } // task or project ID
|
||||
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
|
||||
public Guid PriorityId { get; set; }
|
||||
public ICollection<Guid>? TagIds { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
{
|
||||
public class ForumAttachmentDto
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public Guid TicketId { get; set; } = Guid.Empty;
|
||||
public Guid? CommentId { get; set; }
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public string? Base64Data { get; set; }
|
||||
public int FileSize { get; set; }
|
||||
public string ContentType { get; set; } = string.Empty;
|
||||
public DateTime SentAt { get; set; }
|
||||
}
|
||||
}
|
||||
|
14
Marco.Pms.Model/Dtos/Forum/UpdateCommentDto.cs
Normal file
14
Marco.Pms.Model/Dtos/Forum/UpdateCommentDto.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
{
|
||||
public class UpdateCommentDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TicketId { get; set; }
|
||||
public Guid AuthorId { get; set; }
|
||||
public string MessageText { get; set; } = string.Empty;
|
||||
public DateTime SentAt { get; set; }
|
||||
public Guid? ParentMessageId { get; set; } // For threaded replies
|
||||
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
}
|
18
Marco.Pms.Model/Dtos/Forum/UpdateTicketDto.cs
Normal file
18
Marco.Pms.Model/Dtos/Forum/UpdateTicketDto.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Marco.Pms.Model.Dtos.Forum
|
||||
{
|
||||
public class UpdateTicketDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public Guid StatusId { get; set; }
|
||||
public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback
|
||||
public int CreatedById { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public int LinkedActivityId { get; set; } // task or project ID
|
||||
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
|
||||
public Guid PriorityId { get; set; }
|
||||
public ICollection<Guid>? TagIds { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ namespace Marco.Pms.Model.Forum
|
||||
[ValidateNever]
|
||||
[ForeignKey(nameof(TicketId))]
|
||||
public TicketForum? Ticket { get; set; }
|
||||
public Guid CommentId { get; set; }
|
||||
public Guid? CommentId { get; set; }
|
||||
[ValidateNever]
|
||||
[ForeignKey(nameof(CommentId))]
|
||||
public TicketComment? TicketComment { get; set; }
|
||||
|
@ -4,10 +4,10 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Guid TicketId { get; set; }
|
||||
public TicketForum Ticket { get; set; } = new TicketForum();
|
||||
public TicketForum? Ticket { get; set; }
|
||||
|
||||
public Guid TagId { get; set; }
|
||||
public TicketTagMaster Tag { get; set; } = new TicketTagMaster();
|
||||
public TicketTagMaster? Tag { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
176
Marco.Pms.Model/Mapper/ForumMapper.cs
Normal file
176
Marco.Pms.Model/Mapper/ForumMapper.cs
Normal file
@ -0,0 +1,176 @@
|
||||
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.ViewModels.Forum;
|
||||
|
||||
namespace Marco.Pms.Model.Mapper
|
||||
{
|
||||
public static class ForumMapper
|
||||
{
|
||||
public static TicketForum ToTicketForumFromCreateTicketDto(this CreateTicketDto createTicketDto)
|
||||
{
|
||||
return new TicketForum
|
||||
{
|
||||
Subject = createTicketDto.Subject,
|
||||
Description = createTicketDto.Description,
|
||||
StatusId = createTicketDto.StatusId,
|
||||
TypeId = createTicketDto.TypeId,
|
||||
CreatedById = createTicketDto.CreatedById,
|
||||
CreatedAt = createTicketDto.CreatedAt,
|
||||
LinkedActivityId = createTicketDto.LinkedActivityId,
|
||||
PriorityId = createTicketDto.PriorityId,
|
||||
TenantId = createTicketDto.TenantId,
|
||||
};
|
||||
}
|
||||
public static TicketForum ToTicketForumFromUpdateTicketDto(this UpdateTicketDto updateTicketDto, TicketForum ticket)
|
||||
{
|
||||
return new TicketForum
|
||||
{
|
||||
Id = updateTicketDto.Id,
|
||||
Subject = updateTicketDto.Subject,
|
||||
Description = updateTicketDto.Description,
|
||||
StatusId = updateTicketDto.StatusId,
|
||||
TypeId = updateTicketDto.TypeId,
|
||||
CreatedById = ticket.CreatedById,
|
||||
CreatedAt = ticket.CreatedAt,
|
||||
LinkedActivityId = updateTicketDto.LinkedActivityId,
|
||||
PriorityId = updateTicketDto.PriorityId,
|
||||
TenantId = ticket.TenantId
|
||||
};
|
||||
}
|
||||
|
||||
public static TicketComment ToTicketCommentFromAddCommentDto(this AddCommentDto commentDto)
|
||||
{
|
||||
return new TicketComment
|
||||
{
|
||||
TicketId = commentDto.TicketId,
|
||||
AuthorId = commentDto.AuthorId,
|
||||
MessageText = commentDto.MessageText,
|
||||
SentAt = commentDto.SentAt,
|
||||
ParentMessageId = commentDto.ParentMessageId,
|
||||
TenantId = commentDto.TenantId,
|
||||
};
|
||||
}
|
||||
public static TicketComment ToTicketCommentFromUpdateCommentDto(this UpdateCommentDto updateComment, int tenantId, TicketComment comment)
|
||||
{
|
||||
return new TicketComment
|
||||
{
|
||||
Id = updateComment.Id,
|
||||
TicketId = updateComment.TicketId,
|
||||
AuthorId = comment.AuthorId,
|
||||
MessageText = updateComment.MessageText,
|
||||
SentAt = comment.SentAt,
|
||||
ParentMessageId = updateComment.ParentMessageId,
|
||||
TenantId = tenantId,
|
||||
};
|
||||
}
|
||||
public static TicketAttachment ToTicketAttachmentFromForumAttachmentDto(this ForumAttachmentDto AttachmentDto, Guid ticketId, Guid fileId, Guid? commentId = null)
|
||||
{
|
||||
return new TicketAttachment
|
||||
{
|
||||
TicketId = ticketId,
|
||||
CommentId = commentId,
|
||||
FileName = AttachmentDto.FileName,
|
||||
FileId = fileId,
|
||||
};
|
||||
}
|
||||
|
||||
public static Document ToDocumentFromForumAttachmentDto(this ForumAttachmentDto AttachmentDto, string objectKey, string thumbS3Key, DateTime uploadedAt, int tenantId)
|
||||
{
|
||||
return new Document
|
||||
{
|
||||
FileName = AttachmentDto.FileName,
|
||||
ContentType = AttachmentDto.ContentType,
|
||||
S3Key = objectKey,
|
||||
ThumbS3Key = thumbS3Key,
|
||||
Base64Data = AttachmentDto.Base64Data,
|
||||
FileSize = AttachmentDto.FileSize,
|
||||
UploadedAt = uploadedAt,
|
||||
TenantId = tenantId
|
||||
};
|
||||
}
|
||||
public static ForumTicketVM ToForumTicketVMFromTicketForum(this TicketForum ticket, Employee employee)
|
||||
{
|
||||
return new ForumTicketVM
|
||||
{
|
||||
Id = ticket.Id,
|
||||
Subject = ticket.Subject,
|
||||
Description = ticket.Description,
|
||||
CreatedAt = ticket.CreatedAt,
|
||||
LinkedActivityId = ticket.LinkedActivityId,
|
||||
Status = ticket.TicketStatusMaster.ToTicketStatusVMFromTicketStatusMaster(),
|
||||
Priority = ticket.Priority.ToTicketPriorityVMFromTicketPriorityMaster(),
|
||||
Type = ticket.TicketTypeMaster.ToTicketTypeVMFromTicketTypeMaster(),
|
||||
CreatedBy = employee.ToBasicEmployeeVMFromEmployee(),
|
||||
};
|
||||
}
|
||||
public static TicketAttachmentVM ToTicketAttachmentVMFromTicketAttachment(this TicketAttachment attachment, string preSignedUrl, string thumbPreSignedUrl)
|
||||
{
|
||||
return new TicketAttachmentVM
|
||||
{
|
||||
Id = attachment.Id,
|
||||
TicketId = attachment.TicketId,
|
||||
CommentId = attachment.CommentId,
|
||||
FileName = attachment.FileName,
|
||||
PreSignedUrl = preSignedUrl,
|
||||
ThumbPreSignedUrl = thumbPreSignedUrl
|
||||
};
|
||||
}
|
||||
public static TicketCommentVM ToTicketCommentVMFromTicketComment(this TicketComment comment, Employee employee)
|
||||
{
|
||||
return new TicketCommentVM
|
||||
{
|
||||
Id = comment.Id,
|
||||
TicketId = comment.TicketId,
|
||||
Author = employee.ToBasicEmployeeVMFromEmployee(),
|
||||
MessageText = comment.MessageText,
|
||||
SentAt = comment.SentAt,
|
||||
ParentMessageId = comment.ParentMessageId,
|
||||
Attachments = new List<TicketAttachmentVM>()
|
||||
};
|
||||
}
|
||||
public static TicketStatusVM ToTicketStatusVMFromTicketStatusMaster(this TicketStatusMaster statusMaster)
|
||||
{
|
||||
return new TicketStatusVM
|
||||
{
|
||||
Id = statusMaster.Id,
|
||||
Name = statusMaster.Name,
|
||||
Description = statusMaster.Description,
|
||||
ColorCode = statusMaster.ColorCode,
|
||||
IsDefault = statusMaster.IsDefault
|
||||
};
|
||||
}
|
||||
public static TicketPriorityVM ToTicketPriorityVMFromTicketPriorityMaster(this TicketPriorityMaster priorityMaster)
|
||||
{
|
||||
return new TicketPriorityVM
|
||||
{
|
||||
Id = priorityMaster.Id,
|
||||
Name = priorityMaster.Name,
|
||||
Level = priorityMaster.Level,
|
||||
ColorCode = priorityMaster.ColorCode,
|
||||
IsDefault = priorityMaster.IsDefault
|
||||
};
|
||||
}
|
||||
public static TicketTypeVM ToTicketTypeVMFromTicketTypeMaster(this TicketTypeMaster typeMaster)
|
||||
{
|
||||
return new TicketTypeVM
|
||||
{
|
||||
Id = typeMaster.Id,
|
||||
Name = typeMaster.Name,
|
||||
Description = typeMaster.Description,
|
||||
IsDefault = typeMaster.IsDefault
|
||||
};
|
||||
}
|
||||
public static TicketTagVM ToTicketTagVMFromTicketTagMaster(this TicketTagMaster tagMaster)
|
||||
{
|
||||
return new TicketTagVM
|
||||
{
|
||||
Id = tagMaster.Id,
|
||||
Name = tagMaster.Name,
|
||||
ColorCode = tagMaster.ColorCode,
|
||||
IsDefault = tagMaster.IsDefault
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
14
Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs
Normal file
14
Marco.Pms.Model/ViewModels/DocumentManager/DocumentVM.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
{
|
||||
public class DocumentVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid? BatchId { get; set; }
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public string? PreSignedUrl { get; set; }
|
||||
public string? ThumbPreSignedUrl { get; set; }
|
||||
public long FileSize { get; set; }
|
||||
public string ContentType { get; set; } = string.Empty;
|
||||
public DateTime UploadedAt { get; set; }
|
||||
}
|
||||
}
|
@ -1,6 +1,20 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class ForumTicketVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public TicketStatusVM? Status { get; set; }
|
||||
public TicketTypeVM? Type { get; set; } // QualityIssue, HelpDesk, Feedback
|
||||
public TicketPriorityVM? Priority { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public int LinkedActivityId { get; set; } // task or project ID
|
||||
public ICollection<TicketCommentVM>? Comments { get; set; } // view model
|
||||
public ICollection<TicketAttachmentVM>? Attachments { get; set; } // view model
|
||||
public ICollection<TicketTagVM>? Tags { get; set; }
|
||||
}
|
||||
}
|
||||
|
12
Marco.Pms.Model/ViewModels/Forum/TicketAttachmentVM.cs
Normal file
12
Marco.Pms.Model/ViewModels/Forum/TicketAttachmentVM.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketAttachmentVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TicketId { get; set; }
|
||||
public Guid? CommentId { get; set; }
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public string? PreSignedUrl { get; set; }
|
||||
public string ThumbPreSignedUrl { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
16
Marco.Pms.Model/ViewModels/Forum/TicketCommentVM.cs
Normal file
16
Marco.Pms.Model/ViewModels/Forum/TicketCommentVM.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketCommentVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TicketId { get; set; }
|
||||
public BasicEmployeeVM? Author { get; set; }
|
||||
public string MessageText { get; set; } = string.Empty;
|
||||
public DateTime SentAt { get; set; }
|
||||
public Guid? ParentMessageId { get; set; } // For threaded replies
|
||||
|
||||
public ICollection<TicketAttachmentVM>? Attachments { get; set; }
|
||||
}
|
||||
}
|
12
Marco.Pms.Model/ViewModels/Forum/TicketPriorityVM.cs
Normal file
12
Marco.Pms.Model/ViewModels/Forum/TicketPriorityVM.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketPriorityVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty; // e.g., Low, Medium, High, Critical
|
||||
public int Level { get; set; } // 1 = Low, 2 = Medium...
|
||||
public string? ColorCode { get; set; }
|
||||
public bool IsDefault { get; set; } // true for system defaults
|
||||
|
||||
}
|
||||
}
|
11
Marco.Pms.Model/ViewModels/Forum/TicketStatusVM.cs
Normal file
11
Marco.Pms.Model/ViewModels/Forum/TicketStatusVM.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketStatusVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty; // e.g., "Open", "In Progress"
|
||||
public string? Description { get; set; }
|
||||
public string? ColorCode { get; set; } // e.g., "#FF0000"
|
||||
public bool IsDefault { get; set; } // true for system defaults
|
||||
}
|
||||
}
|
10
Marco.Pms.Model/ViewModels/Forum/TicketTagVM.cs
Normal file
10
Marco.Pms.Model/ViewModels/Forum/TicketTagVM.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketTagVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty; // e.g., "Bug", "UI", "Urgent"
|
||||
public string? ColorCode { get; set; }
|
||||
public bool IsDefault { get; set; }
|
||||
}
|
||||
}
|
11
Marco.Pms.Model/ViewModels/Forum/TicketTypeVM.cs
Normal file
11
Marco.Pms.Model/ViewModels/Forum/TicketTypeVM.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Forum
|
||||
{
|
||||
public class TicketTypeVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty; // e.g., "Quality Issue"
|
||||
public string? Description { get; set; }
|
||||
public bool IsDefault { get; set; } // true for system defaults
|
||||
|
||||
}
|
||||
}
|
@ -1,73 +1,796 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Authentication;
|
||||
using Marco.Pms.Model.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Forum;
|
||||
using Marco.Pms.Model.Dtos.Util;
|
||||
using Marco.Pms.Model.Industries;
|
||||
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.Identity;
|
||||
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 UserManager<IdentityUser> _userManager;
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly JwtSettings _jwtSettings;
|
||||
private readonly RefreshTokenService _refreshTokenService;
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly EmployeeHelper _employeeHelper;
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly S3UploadService _s3Service;
|
||||
private readonly ILoggingService _logger;
|
||||
//string tenentId = "1";
|
||||
public ForumController(UserManager<IdentityUser> userManager, ApplicationDbContext context, JwtSettings jwtSettings, RefreshTokenService refreshTokenService,
|
||||
IEmailSender emailSender, IConfiguration configuration, EmployeeHelper employeeHelper)
|
||||
public ForumController(ApplicationDbContext context, S3UploadService s3Service, UserHelper userHelper, ILoggingService logger)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_jwtSettings = jwtSettings;
|
||||
_refreshTokenService = refreshTokenService;
|
||||
_emailSender = emailSender;
|
||||
_configuration = configuration;
|
||||
_employeeHelper = employeeHelper;
|
||||
_context = context;
|
||||
_userHelper = userHelper;
|
||||
_s3Service = s3Service;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpPost("tickets")]
|
||||
[HttpPost("ticket")]
|
||||
public async Task<IActionResult> CreateNewTicket([FromBody] CreateTicketDto createTicketDto)
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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)); ;
|
||||
}
|
||||
|
||||
[HttpPost("tickets/{id}/comment")]
|
||||
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)
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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));
|
||||
}
|
||||
|
||||
[HttpPost("tickets/{id}/attachments")]
|
||||
public async Task<IActionResult> UploadAttachments([FromBody] ForumAttachmentDto forumAttachmentDto)
|
||||
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)
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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));
|
||||
}
|
||||
|
||||
[HttpPatch("tickets/{id}/status")]
|
||||
public async Task<IActionResult> UpdateTicketStatus([FromBody] InquiryDto inquiryDto)
|
||||
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)
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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));
|
||||
}
|
||||
[HttpGet("tickets/{id}")]
|
||||
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)
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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([FromBody] InquiryDto inquiryDto)
|
||||
public async Task<IActionResult> ListTickets()
|
||||
{
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Industry not found.", "Industry not found.", 404));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Dtos.Activities;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.Forum;
|
||||
using Marco.Pms.Model.Mapper;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Forum;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -18,10 +21,12 @@ namespace Marco.Pms.Services.Controllers
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly UserHelper _userHelper;
|
||||
public MasterController(ApplicationDbContext context, UserHelper userHelper)
|
||||
private readonly ILoggingService _logger;
|
||||
public MasterController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger)
|
||||
{
|
||||
_context = context;
|
||||
_userHelper = userHelper;
|
||||
_logger = logger;
|
||||
}
|
||||
[HttpGet]
|
||||
[Route("activities")]
|
||||
@ -30,14 +35,15 @@ namespace Marco.Pms.Services.Controllers
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var activities = await _context.ActivityMasters.Where(c => c.TenantId == tenantId && c.IsActive == true).ToListAsync();
|
||||
List<ActivityVM> activitiesVM = new List<ActivityVM>();
|
||||
foreach (var activity in activities) {
|
||||
foreach (var activity in activities)
|
||||
{
|
||||
var checkList = await _context.ActivityCheckLists.Where(c => c.TenantId == tenantId && c.ActivityId == activity.Id).ToListAsync();
|
||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
||||
if(checkList != null)
|
||||
if (checkList != null)
|
||||
{
|
||||
foreach (ActivityCheckList check in checkList)
|
||||
{
|
||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id,false);
|
||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
|
||||
checkListVM.Add(checkVM);
|
||||
}
|
||||
}
|
||||
@ -45,7 +51,8 @@ namespace Marco.Pms.Services.Controllers
|
||||
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
|
||||
activitiesVM.Add(activityVM);
|
||||
}
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activitiesVM, "Success.", 200));
|
||||
_logger.LogInfo("{count} activity records fetched successfully from tenant {tenantId}", activitiesVM.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activitiesVM, System.String.Format("{0} activity records fetched successfully", activitiesVM.Count), 200));
|
||||
}
|
||||
|
||||
[HttpPost("activity")]
|
||||
@ -55,81 +62,87 @@ namespace Marco.Pms.Services.Controllers
|
||||
var employee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
if (employee.TenantId != tenantId)
|
||||
{
|
||||
_logger.LogWarning("User from tenant {employeeTenantId} tries to access data from tenant {tenantId}", employee.TenantId, tenantId);
|
||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Current tenant did not match with user's tenant", "Current tenant did not match with user's tenant", 401));
|
||||
}
|
||||
var activityMaster = createActivity.ToActivityMasterFromCreateActivityMasterDto(tenantId);
|
||||
_context.ActivityMasters.Add(activityMaster);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
if (createActivity.CheckList != null) {
|
||||
List<ActivityCheckList> activityCheckList = new List<ActivityCheckList>();
|
||||
foreach (var check in createActivity.CheckList)
|
||||
{
|
||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId,activityMaster.Id);
|
||||
activityCheckList.Add(checkList);
|
||||
}
|
||||
_context.ActivityCheckLists.AddRange(activityCheckList);
|
||||
await _context.SaveChangesAsync();
|
||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
||||
foreach (ActivityCheckList check in activityCheckList)
|
||||
{
|
||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activityMaster.Id,false);
|
||||
checkListVM.Add(checkVM);
|
||||
}
|
||||
|
||||
ActivityVM activityVM = activityMaster.ToActivityVMFromActivityMaster(checkListVM);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "Activity created successfully", 200));
|
||||
}
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Check List is Empty", "Check List is Empty", 400));
|
||||
}
|
||||
|
||||
[HttpPost("edit/{id}")]
|
||||
public async Task<IActionResult> UpdateActivity(int id, [FromBody] CreateActivityMasterDto createActivity)
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var employee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
ActivityMaster? activity = await _context.ActivityMasters.FirstOrDefaultAsync(x => x.Id == id && x.IsActive == true && x.TenantId == tenantId);
|
||||
if (activity != null && createActivity.UnitOfMeasurement != null && createActivity.ActivityName != null) {
|
||||
|
||||
activity.ActivityName = createActivity.ActivityName;
|
||||
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement;
|
||||
|
||||
if (createActivity.CheckList != null)
|
||||
{
|
||||
List<ActivityCheckList> activityCheckList = new List<ActivityCheckList>();
|
||||
foreach (var check in createActivity.CheckList)
|
||||
{
|
||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId,activity.Id);
|
||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activityMaster.Id);
|
||||
activityCheckList.Add(checkList);
|
||||
}
|
||||
_context.ActivityCheckLists.AddRange(activityCheckList);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
foreach (ActivityCheckList check in activityCheckList)
|
||||
{
|
||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activityMaster.Id, false);
|
||||
checkListVM.Add(checkVM);
|
||||
}
|
||||
}
|
||||
ActivityVM activityVM = activityMaster.ToActivityVMFromActivityMaster(checkListVM);
|
||||
|
||||
_logger.LogInfo("activity created successfully from tenant {tenantId}", tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity created successfully", 200));
|
||||
}
|
||||
|
||||
[HttpPost("activity/edit/{id}")]
|
||||
public async Task<IActionResult> UpdateActivity(int id, [FromBody] CreateActivityMasterDto createActivity)
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var employee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
ActivityMaster? activity = await _context.ActivityMasters.FirstOrDefaultAsync(x => x.Id == id && x.IsActive == true && x.TenantId == tenantId);
|
||||
if (activity != null && createActivity.UnitOfMeasurement != null && createActivity.ActivityName != null)
|
||||
{
|
||||
|
||||
activity.ActivityName = createActivity.ActivityName;
|
||||
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement;
|
||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
||||
|
||||
if (createActivity.CheckList != null)
|
||||
{
|
||||
List<ActivityCheckList> activityCheckList = new List<ActivityCheckList>();
|
||||
foreach (var check in createActivity.CheckList)
|
||||
{
|
||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id);
|
||||
activityCheckList.Add(checkList);
|
||||
}
|
||||
_context.ActivityCheckLists.UpdateRange(activityCheckList);
|
||||
await _context.SaveChangesAsync();
|
||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
||||
|
||||
foreach (ActivityCheckList check in activityCheckList)
|
||||
{
|
||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
|
||||
checkListVM.Add(checkVM);
|
||||
}
|
||||
|
||||
}
|
||||
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "Activity created successfully", 200));
|
||||
_logger.LogInfo("activity updated successfully from tenant {tenantId}", tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity updated successfully", 200));
|
||||
}
|
||||
_logger.LogError("Activity {ActivityId} not found", id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404));
|
||||
}
|
||||
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Activity no found", "Activity no found", 404));
|
||||
}
|
||||
#nullable disable
|
||||
[HttpDelete("delete/{id}")]
|
||||
[HttpDelete("activity/delete/{id}")]
|
||||
public async Task<IActionResult> DeleteActivity(int Id)
|
||||
{
|
||||
int tenantId = _userHelper.GetTenantId();
|
||||
var activity = await _context.ActivityMasters.FirstOrDefaultAsync(a => a.Id == Id && a.TenantId == tenantId);
|
||||
if(activity != null)
|
||||
if (activity != null)
|
||||
{
|
||||
activity.IsActive = false;
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
return Ok(ApiResponse<object>.SuccessResponse(null, "Activity Deleted Successfully", 200));
|
||||
_logger.LogInfo("Activity Deleted Successfully from tenant {tenantId}", tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Activity Deleted Successfully", 200));
|
||||
}
|
||||
[HttpGet]
|
||||
[Route("industries")]
|
||||
@ -138,7 +151,68 @@ namespace Marco.Pms.Services.Controllers
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var industries = await _context.Industries.ToListAsync();
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(industries, "Success.", 200));
|
||||
_logger.LogInfo("{count} industry records fetched successfully from tenant {tenantId}", industries.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(industries, System.String.Format("{0} industry records fetched successfully", industries.Count), 200));
|
||||
}
|
||||
|
||||
[HttpGet("ticket-status")]
|
||||
public async Task<IActionResult> GetTicketStatusMaster()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
List<TicketStatusVM> statusVMs = new List<TicketStatusVM>();
|
||||
List<TicketStatusMaster> statusMasters = await _context.TicketStatusMasters.Where(s => s.TenantId == tenantId).ToListAsync();
|
||||
foreach (var statusMaster in statusMasters)
|
||||
{
|
||||
statusVMs.Add(statusMaster.ToTicketStatusVMFromTicketStatusMaster());
|
||||
}
|
||||
|
||||
_logger.LogInfo("{count} Ticket Status records fetched successfully from tenant {tenantId}", statusVMs.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(statusVMs, System.String.Format("{0} Ticket Status records fetched successfully", statusVMs.Count), 200));
|
||||
}
|
||||
|
||||
[HttpGet("ticket-types")]
|
||||
public async Task<IActionResult> GetTicketTypeMaster()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
List<TicketTypeVM> typeVMs = new List<TicketTypeVM>();
|
||||
List<TicketTypeMaster> typeMasters = await _context.TicketTypeMasters.Where(s => s.TenantId == tenantId).ToListAsync();
|
||||
foreach (var typeMaster in typeMasters)
|
||||
{
|
||||
typeVMs.Add(typeMaster.ToTicketTypeVMFromTicketTypeMaster());
|
||||
}
|
||||
|
||||
_logger.LogInfo("{count} Ticket Type records fetched successfully from tenant {tenantId}", typeVMs.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(typeVMs, System.String.Format("{0} Ticket Type records fetched successfully", typeVMs.Count), 200));
|
||||
}
|
||||
|
||||
[HttpGet("ticket-priorities")]
|
||||
public async Task<IActionResult> GetTicketPriorityMaster()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
List<TicketPriorityVM> priorityVMs = new List<TicketPriorityVM>();
|
||||
List<TicketPriorityMaster> priorityMasters = await _context.TicketPriorityMasters.Where(s => s.TenantId == tenantId).ToListAsync();
|
||||
foreach (var priorityMaster in priorityMasters)
|
||||
{
|
||||
priorityVMs.Add(priorityMaster.ToTicketPriorityVMFromTicketPriorityMaster());
|
||||
}
|
||||
|
||||
_logger.LogInfo("{count} Ticket Priority records fetched successfully from tenant {tenantId}", priorityVMs.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(priorityVMs, System.String.Format("{0} Ticket Priority records fetched successfully", priorityVMs.Count), 200));
|
||||
}
|
||||
|
||||
[HttpGet("ticket-tags")]
|
||||
public async Task<IActionResult> GetTicketTagMaster()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
List<TicketTagVM> tagVMs = new List<TicketTagVM>();
|
||||
List<TicketTagMaster> tagMasters = await _context.TicketTagMasters.Where(s => s.TenantId == tenantId).ToListAsync();
|
||||
foreach (var tagMaster in tagMasters)
|
||||
{
|
||||
tagVMs.Add(tagMaster.ToTicketTagVMFromTicketTagMaster());
|
||||
}
|
||||
|
||||
_logger.LogInfo("{count} Ticket Tag records fetched successfully from tenant {tenantId}", tagVMs.Count, tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(tagVMs, System.String.Format("{0} Ticket Tag records fetched successfully", tagVMs.Count), 200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,12 +38,19 @@ namespace Marco.Pms.Services.Service
|
||||
ContentType = contentType,
|
||||
AutoCloseStream = true
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var transferUtility = new TransferUtility(_s3Client);
|
||||
await transferUtility.UploadAsync(uploadRequest);
|
||||
_logger.LogInfo("File uploaded to Amazon S3");
|
||||
return objectKey;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("{error} while uploading file to S3", ex.Message);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public async Task<string> GeneratePreSignedUrlAsync(string objectKey)
|
||||
{
|
||||
int expiresInMinutes = 1;
|
||||
@ -54,11 +61,38 @@ namespace Marco.Pms.Services.Service
|
||||
Expires = DateTime.UtcNow.AddMinutes(expiresInMinutes),
|
||||
Verb = HttpVerb.GET // for download
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
string url = _s3Client.GetPreSignedURL(request);
|
||||
_logger.LogInfo("Requested presigned url from Amazon S3");
|
||||
return url;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("{error} while requesting presigned url from Amazon S3", ex.Message);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public async Task<bool> DeleteFileAsync(string objectKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
var deleteRequest = new DeleteObjectRequest
|
||||
{
|
||||
BucketName = _bucketName,
|
||||
Key = objectKey
|
||||
};
|
||||
|
||||
var response = await _s3Client.DeleteObjectAsync(deleteRequest);
|
||||
_logger.LogInfo("File deleted from Amazon S3");
|
||||
return response.HttpStatusCode == System.Net.HttpStatusCode.NoContent;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("{error} while deleting from Amazon S3", ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public string GenerateFileName(string contentType, int tenantId, string? name)
|
||||
{
|
||||
string extenstion = contentType.Split("/")[1];
|
||||
|
Loading…
x
Reference in New Issue
Block a user