Added an additional column to the ticket forum table to store the linked project ID, and updated both the view models and data transfer models accordingly.

This commit is contained in:
ashutosh.nehete 2025-04-25 21:47:06 +05:30
parent ace2fe7d54
commit c338140210
9 changed files with 2802 additions and 14 deletions

View File

@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_ProjectId_Column_In_TicketForum_Table : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "LinkedActivityId",
table: "Tickets",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddColumn<int>(
name: "LinkedProjectId",
table: "Tickets",
type: "int",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LinkedProjectId",
table: "Tickets");
migrationBuilder.AlterColumn<int>(
name: "LinkedActivityId",
table: "Tickets",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
}
}
}

View File

@ -1227,7 +1227,10 @@ namespace Marco.Pms.DataAccess.Migrations
.IsRequired() .IsRequired()
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<int>("LinkedActivityId") b.Property<int?>("LinkedActivityId")
.HasColumnType("int");
b.Property<int>("LinkedProjectId")
.HasColumnType("int"); .HasColumnType("int");
b.Property<Guid>("PriorityId") b.Property<Guid>("PriorityId")

View File

@ -9,7 +9,8 @@
public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback
public int CreatedById { get; set; } public int CreatedById { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public int LinkedActivityId { get; set; } // task or project ID public int LinkedProjectId { get; set; }
public int? LinkedActivityId { get; set; } // task or project ID
public ICollection<ForumAttachmentDto>? Attachments { get; set; } public ICollection<ForumAttachmentDto>? Attachments { get; set; }
public Guid PriorityId { get; set; } public Guid PriorityId { get; set; }
public ICollection<Guid>? TagIds { get; set; } public ICollection<Guid>? TagIds { get; set; }

View File

@ -9,7 +9,8 @@
public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback
public int CreatedById { get; set; } public int CreatedById { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public int LinkedActivityId { get; set; } // task or project ID public int LinkedProjectId { get; set; }
public int? LinkedActivityId { get; set; } // task or project ID
public ICollection<ForumAttachmentDto>? Attachments { get; set; } public ICollection<ForumAttachmentDto>? Attachments { get; set; }
public Guid PriorityId { get; set; } public Guid PriorityId { get; set; }
public ICollection<Guid>? TagIds { get; set; } public ICollection<Guid>? TagIds { get; set; }

View File

@ -20,7 +20,9 @@ namespace Marco.Pms.Model.Forum
public TicketTypeMaster? TicketTypeMaster { get; set; } public TicketTypeMaster? TicketTypeMaster { get; set; }
public int CreatedById { get; set; } public int CreatedById { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public int LinkedActivityId { get; set; } // task or project ID
public int LinkedProjectId { get; set; }
public int? LinkedActivityId { get; set; } // task or project ID
//public ICollection<TicketComment>? Comments { get; set; } // view model //public ICollection<TicketComment>? Comments { get; set; } // view model
//public ICollection<TicketAttachment>? Attachments { get; set; } // view model //public ICollection<TicketAttachment>? Attachments { get; set; } // view model

View File

@ -18,6 +18,7 @@ namespace Marco.Pms.Model.Mapper
TypeId = createTicketDto.TypeId, TypeId = createTicketDto.TypeId,
CreatedById = createTicketDto.CreatedById, CreatedById = createTicketDto.CreatedById,
CreatedAt = createTicketDto.CreatedAt, CreatedAt = createTicketDto.CreatedAt,
LinkedProjectId = createTicketDto.LinkedProjectId,
LinkedActivityId = createTicketDto.LinkedActivityId, LinkedActivityId = createTicketDto.LinkedActivityId,
PriorityId = createTicketDto.PriorityId, PriorityId = createTicketDto.PriorityId,
TenantId = createTicketDto.TenantId, TenantId = createTicketDto.TenantId,
@ -34,7 +35,8 @@ namespace Marco.Pms.Model.Mapper
TypeId = updateTicketDto.TypeId, TypeId = updateTicketDto.TypeId,
CreatedById = ticket.CreatedById, CreatedById = ticket.CreatedById,
CreatedAt = ticket.CreatedAt, CreatedAt = ticket.CreatedAt,
LinkedActivityId = updateTicketDto.LinkedActivityId, LinkedProjectId = ticket.LinkedProjectId,
LinkedActivityId = ticket.LinkedActivityId,
PriorityId = updateTicketDto.PriorityId, PriorityId = updateTicketDto.PriorityId,
TenantId = ticket.TenantId TenantId = ticket.TenantId
}; };
@ -98,6 +100,7 @@ namespace Marco.Pms.Model.Mapper
Subject = ticket.Subject, Subject = ticket.Subject,
Description = ticket.Description, Description = ticket.Description,
CreatedAt = ticket.CreatedAt, CreatedAt = ticket.CreatedAt,
LinkedProjectId = ticket.LinkedProjectId,
LinkedActivityId = ticket.LinkedActivityId, LinkedActivityId = ticket.LinkedActivityId,
Status = ticket.TicketStatusMaster.ToTicketStatusVMFromTicketStatusMaster(), Status = ticket.TicketStatusMaster.ToTicketStatusVMFromTicketStatusMaster(),
Priority = ticket.Priority.ToTicketPriorityVMFromTicketPriorityMaster(), Priority = ticket.Priority.ToTicketPriorityVMFromTicketPriorityMaster(),

View File

@ -12,7 +12,10 @@ namespace Marco.Pms.Model.ViewModels.Forum
public TicketPriorityVM? Priority { get; set; } public TicketPriorityVM? Priority { get; set; }
public BasicEmployeeVM? CreatedBy { get; set; } public BasicEmployeeVM? CreatedBy { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public int LinkedActivityId { get; set; } // task or project ID public int LinkedProjectId { get; set; }
public string? ProjectName { get; set; }
public int? LinkedActivityId { get; set; } // task or project ID
public string? ActivityName { get; set; }
public ICollection<TicketCommentVM>? Comments { get; set; } // view model public ICollection<TicketCommentVM>? Comments { get; set; } // view model
public ICollection<TicketAttachmentVM>? Attachments { get; set; } // view model public ICollection<TicketAttachmentVM>? Attachments { get; set; } // view model
public ICollection<TicketTagVM>? Tags { get; set; } public ICollection<TicketTagVM>? Tags { get; set; }

View File

@ -4,6 +4,7 @@ using Marco.Pms.Model.Dtos.Forum;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Forum; using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Forum; using Marco.Pms.Model.ViewModels.Forum;
using Marco.Pms.Services.Service; using Marco.Pms.Services.Service;
@ -143,7 +144,21 @@ namespace Marco.Pms.Services.Controllers
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl)); attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
} }
ticketVM.Attachments = attachmentVMs; ticketVM.Attachments = attachmentVMs;
_logger.LogInfo("Ticket created by Employee {EmployeeId}", ticketForum.CreatedById); Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticketForum.LinkedProjectId) ?? new Project();
ticketVM.ProjectName = project.Name;
if (createTicketDto.LinkedActivityId != null && createTicketDto.LinkedActivityId != 0)
{
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticketForum.LinkedActivityId) ?? new WorkItem();
if (workItem.ActivityMaster != null)
{
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
}
else
{
ticketVM.ActivityName = "";
}
}
_logger.LogInfo("Ticket created by Employee {EmployeeId} for project {ProjectId}", ticketForum.CreatedById, project.Id);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Created Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Created Successfully", 200));
} }
_logger.LogWarning("Employee {EmployeeId} tries to create ticket in different Tenant", createTicketDto.CreatedById); _logger.LogWarning("Employee {EmployeeId} tries to create ticket in different Tenant", createTicketDto.CreatedById);
@ -312,6 +327,20 @@ namespace Marco.Pms.Services.Controllers
} }
ticketVM.Comments = commentVMs; ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs; ticketVM.Attachments = ticketAttachmentVMs;
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticketForum.LinkedProjectId) ?? new Project();
ticketVM.ProjectName = project.Name;
if (updateTicketDto.LinkedActivityId != null && updateTicketDto.LinkedActivityId != 0)
{
WorkItem workItem = await _context.WorkItems.Include(w => w.ActivityMaster).FirstOrDefaultAsync(w => w.Id == ticketForum.LinkedActivityId) ?? new WorkItem();
if (workItem.ActivityMaster != null)
{
ticketVM.ActivityName = workItem.ActivityMaster.ActivityName;
}
else
{
ticketVM.ActivityName = "";
}
}
_logger.LogInfo("Ticket {TicketId} updated", updateTicketDto.Id); _logger.LogInfo("Ticket {TicketId} updated", updateTicketDto.Id);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Updated Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Updated Successfully", 200));
} }
@ -406,7 +435,7 @@ namespace Marco.Pms.Services.Controllers
} }
commentVM.Attachments = attachmentVMs; commentVM.Attachments = attachmentVMs;
_logger.LogInfo("User {ApplicationUserId} commented on a ticket", comment.AuthorId); _logger.LogInfo("User {ApplicationUserId} commented on a ticket{TicketId}", comment.AuthorId, comment.TicketId);
return Ok(ApiResponse<object>.SuccessResponse(commentVM, "Comment Created Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(commentVM, "Comment Created Successfully", 200));
} }
[HttpPost("ticket/comment/edit")] [HttpPost("ticket/comment/edit")]
@ -535,6 +564,8 @@ namespace Marco.Pms.Services.Controllers
int tenantId = _userHelper.GetTenantId(); int tenantId = _userHelper.GetTenantId();
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>(); List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
TicketAttachment attachment = new TicketAttachment();
foreach (var forumAttachmentDto in forumAttachmentDtos) foreach (var forumAttachmentDto in forumAttachmentDtos)
{ {
byte[] fileBytes; byte[] fileBytes;
@ -568,7 +599,7 @@ namespace Marco.Pms.Services.Controllers
_context.Documents.Add(document); _context.Documents.Add(document);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var attachment = forumAttachmentDto.ToTicketAttachmentFromForumAttachmentDto(forumAttachmentDto.TicketId, document.Id, forumAttachmentDto.CommentId); attachment = forumAttachmentDto.ToTicketAttachmentFromForumAttachmentDto(forumAttachmentDto.TicketId, document.Id, forumAttachmentDto.CommentId);
_context.TicketAttachments.Add(attachment); _context.TicketAttachments.Add(attachment);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@ -578,7 +609,14 @@ namespace Marco.Pms.Services.Controllers
ticketAttachmentVMs.Add(attachmentVM); ticketAttachmentVMs.Add(attachmentVM);
} }
_logger.LogInfo("Attachments were added"); 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)); return Ok(ApiResponse<object>.SuccessResponse(ticketAttachmentVMs, "attechments added Successfully", 200));
} }
@ -644,8 +682,21 @@ namespace Marco.Pms.Services.Controllers
} }
ticketVM.Comments = commentVMs; ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs; ticketVM.Attachments = ticketAttachmentVMs;
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticket.LinkedProjectId) ?? new Project();
_logger.LogInfo("Status of Ticket {TicketId} is changes to {status}", id, ticket.TicketStatusMaster.Name); ticketVM.ProjectName = project.Name;
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != 0)
{
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, ticket.TicketStatusMaster.Name);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
} }
[HttpGet("ticket/{id}")] [HttpGet("ticket/{id}")]
@ -706,8 +757,21 @@ namespace Marco.Pms.Services.Controllers
} }
ticketVM.Comments = commentVMs; ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs; ticketVM.Attachments = ticketAttachmentVMs;
Project project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == ticket.LinkedProjectId) ?? new Project();
_logger.LogInfo("Fetched Ticket {TicketId}", id); ticketVM.ProjectName = project.Name;
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != 0)
{
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);
return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(ticketVM, "Ticket Fetched Successfully", 200));
} }
@ -718,6 +782,8 @@ namespace Marco.Pms.Services.Controllers
List<TicketForum> tickets = await _context.Tickets.Include(t => t.TicketTypeMaster).Include(t => t.TicketStatusMaster).Include(t => t.Priority).Where(t => t.TenantId == tenantId).ToListAsync(); 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 createdByIds = tickets.Select(t => t.CreatedById).ToList();
var ticketIds = tickets.Select(t => t.Id).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(); List<TicketComment> ticketComments = await _context.TicketComments.Where(c => ticketIds.Contains(c.TicketId)).ToListAsync();
var authorIds = ticketComments.Select(c => c.AuthorId.ToString()).ToList(); var authorIds = ticketComments.Select(c => c.AuthorId.ToString()).ToList();
@ -734,6 +800,10 @@ namespace Marco.Pms.Services.Controllers
List<Document> documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync(); 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>(); List<ForumTicketVM> ticketVMs = new List<ForumTicketVM>();
foreach (var ticket in tickets) foreach (var ticket in tickets)
{ {
@ -787,6 +857,20 @@ namespace Marco.Pms.Services.Controllers
ticketVM.Comments = commentVMs; ticketVM.Comments = commentVMs;
ticketVM.Attachments = ticketAttachmentVMs; ticketVM.Attachments = ticketAttachmentVMs;
ticketVM.Tags = tagVMs; ticketVM.Tags = tagVMs;
Project project = projects.Find(p => p.Id == ticket.LinkedProjectId) ?? new Project();
ticketVM.ProjectName = project.Name;
if (ticket.LinkedActivityId != null && ticket.LinkedActivityId != 0)
{
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); ticketVMs.Add(ticketVM);
} }
_logger.LogInfo("{count} tickets records fetched successfully from tenant {tenantId}", ticketVMs.Count, tenantId); _logger.LogInfo("{count} tickets records fetched successfully from tenant {tenantId}", ticketVMs.Count, tenantId);