Initial commit: HelpDesk ICHN - .NET 10 backend + Next.js 16 frontend

This commit is contained in:
Nurfog committed 2026-09-10 10:20:51 -03:00
commit 359f0caf85
90 files changed
+13395

No files matched your search

@@ -0,0 +1,128 @@
using HelpDesk.Models.Entities;
using HelpDesk.Models.Enums;
using Microsoft.EntityFrameworkCore;
namespace HelpDesk.Data.Repositories;
public class TicketRepository : ITicketRepository
{
private readonly HelpDeskDbContext _context;
public TicketRepository(HelpDeskDbContext context)
{
_context = context;
}
private IQueryable<Ticket> GetQueryable()
=> _context.Tickets
.Include(t => t.Requester)
.Include(t => t.Assignee)
.Include(t => t.Group)
.Include(t => t.SlaPolicy)
.Include(t => t.Comments);
public async Task<Ticket?> GetByIdAsync(Guid id)
=> await GetQueryable().FirstOrDefaultAsync(t => t.Id == id);
public async Task<IEnumerable<Ticket>> GetAllAsync(TicketStatus? status, TicketPriority? priority, Guid? assigneeId, Guid? requesterId, int page = 1, int pageSize = 20)
{
var query = GetQueryable().AsQueryable();
if (status.HasValue) query = query.Where(t => t.Status == status.Value);
if (priority.HasValue) query = query.Where(t => t.Priority == priority.Value);
if (assigneeId.HasValue) query = query.Where(t => t.AssigneeId == assigneeId.Value);
if (requesterId.HasValue) query = query.Where(t => t.RequesterId == requesterId.Value);
return await query.OrderByDescending(t => t.CreatedAt)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
public async Task<int> GetCountAsync(TicketStatus? status, TicketPriority? priority, Guid? assigneeId, Guid? requesterId)
{
var query = _context.Tickets.AsQueryable();
if (status.HasValue) query = query.Where(t => t.Status == status.Value);
if (priority.HasValue) query = query.Where(t => t.Priority == priority.Value);
if (assigneeId.HasValue) query = query.Where(t => t.AssigneeId == assigneeId.Value);
if (requesterId.HasValue) query = query.Where(t => t.RequesterId == requesterId.Value);
return await query.CountAsync();
}
public async Task<Ticket> CreateAsync(Ticket ticket)
{
_context.Tickets.Add(ticket);
await _context.SaveChangesAsync();
return ticket;
}
public async Task<Ticket?> UpdateAsync(Ticket ticket)
{
var existing = await _context.Tickets.FindAsync(ticket.Id);
if (existing == null) return null;
existing.Title = ticket.Title;
existing.Description = ticket.Description;
existing.Priority = ticket.Priority;
existing.Status = ticket.Status;
existing.AssigneeId = ticket.AssigneeId;
existing.GroupId = ticket.GroupId;
existing.SlaPolicyId = ticket.SlaPolicyId;
existing.UpdatedAt = DateTime.UtcNow;
if (ticket.Status == TicketStatus.Resolved && existing.ResolvedAt == null)
existing.ResolvedAt = DateTime.UtcNow;
if (ticket.Status == TicketStatus.Closed && existing.ClosedAt == null)
existing.ClosedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
return existing;
}
public async Task<bool> DeleteAsync(Guid id)
{
var ticket = await _context.Tickets.FindAsync(id);
if (ticket == null) return false;
_context.Tickets.Remove(ticket);
await _context.SaveChangesAsync();
return true;
}
public async Task<int> GetTotalCountAsync()
=> await _context.Tickets.CountAsync();
public async Task<int> GetCountByStatusAsync(TicketStatus status)
=> await _context.Tickets.CountAsync(t => t.Status == status);
public async Task<int> GetCountByPriorityAsync(TicketPriority priority)
=> await _context.Tickets.CountAsync(t => t.Priority == priority);
public async Task<double> GetAverageResponseTimeAsync()
{
var tickets = await _context.Tickets
.Where(t => t.Comments.Any())
.Select(t => new
{
t.CreatedAt,
FirstCommentAt = t.Comments.OrderBy(c => c.CreatedAt).Select(c => c.CreatedAt).FirstOrDefault()
})
.Where(t => t.FirstCommentAt != default(DateTime))
.ToListAsync();
if (!tickets.Any()) return 0;
return tickets.Average(t => (t.FirstCommentAt - t.CreatedAt).TotalMinutes);
}
public async Task<double> GetAverageResolutionTimeAsync()
{
var tickets = await _context.Tickets
.Where(t => t.ResolvedAt.HasValue)
.Select(t => new { t.CreatedAt, t.ResolvedAt })
.ToListAsync();
if (!tickets.Any()) return 0;
return tickets.Average(t => (t.ResolvedAt!.Value - t.CreatedAt).TotalMinutes);
}
}