Implement support ticket system with role request and bug report functionalities
- Introduced a new support ticket system allowing users to submit bug reports and role requests. - Implemented endpoints for creating, updating, and managing support tickets, including file attachments. - Enhanced Telegram bot integration to handle role requests directly within the bot, enabling admins to approve or reject requests without accessing the website. - Updated database schema to include support ticket entities and their relationships. - Improved API documentation to reflect new support ticket endpoints and their usage. - Added necessary localization for support ticket features in both Russian and English.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using PnvPanel.Domain.Common;
|
||||
using PnvPanel.Domain.Exceptions;
|
||||
|
||||
namespace PnvPanel.Domain.Support;
|
||||
|
||||
/// <summary>
|
||||
/// Обращение в поддержку: баг/предложение (свободная форма) либо заявка на роль (существующая роль
|
||||
/// или параметры новой). Текст обращения и переписка — в TicketComment, отдельной таблицей (не
|
||||
/// навигационная коллекция — см. конвенцию проекта на плоских сущностях, ср. TrafficSample/VpnConfig).
|
||||
/// Для RoleRequest заполнен либо RequestedRoleId, либо Proposed* — гарантируется отдельными фабриками,
|
||||
/// а не runtime-проверкой одного универсального конструктора.
|
||||
/// </summary>
|
||||
public sealed class SupportTicket : Entity
|
||||
{
|
||||
public Guid UserId { get; private set; }
|
||||
public TicketType Type { get; private set; }
|
||||
public TicketStatus Status { get; private set; }
|
||||
public Guid? RequestedRoleId { get; private set; }
|
||||
public string? ProposedRoleName { get; private set; }
|
||||
public int? ProposedMaxConfigs { get; private set; }
|
||||
public int? ProposedMaxIpLimit { get; private set; }
|
||||
public DateTimeOffset CreatedAt { get; private set; }
|
||||
|
||||
private SupportTicket()
|
||||
{
|
||||
}
|
||||
|
||||
public static SupportTicket CreateBugReport(Guid userId)
|
||||
{
|
||||
return new SupportTicket
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserId = userId,
|
||||
Type = TicketType.BugReport,
|
||||
Status = TicketStatus.Open,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
}
|
||||
|
||||
public static SupportTicket CreateRoleRequestForExistingRole(Guid userId, Guid roleId)
|
||||
{
|
||||
return new SupportTicket
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserId = userId,
|
||||
Type = TicketType.RoleRequest,
|
||||
Status = TicketStatus.Open,
|
||||
RequestedRoleId = roleId,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
}
|
||||
|
||||
public static SupportTicket CreateRoleRequestForNewRole(Guid userId, string name, int maxConfigs, int maxIpLimit)
|
||||
{
|
||||
return new SupportTicket
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserId = userId,
|
||||
Type = TicketType.RoleRequest,
|
||||
Status = TicketStatus.Open,
|
||||
ProposedRoleName = name,
|
||||
ProposedMaxConfigs = maxConfigs,
|
||||
ProposedMaxIpLimit = maxIpLimit,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Решено (в т.ч. заявка на роль одобрена — роль выдаётся оркестрацией на уровне Application).</summary>
|
||||
public void Resolve()
|
||||
{
|
||||
if (Status != TicketStatus.Open)
|
||||
throw new DomainException($"Нельзя перевести в Resolved тикет в статусе {Status}.");
|
||||
|
||||
Status = TicketStatus.Resolved;
|
||||
}
|
||||
|
||||
/// <summary>Финальное состояние — обратного пути нет (в т.ч. заявка на роль отклонена).</summary>
|
||||
public void Close()
|
||||
{
|
||||
if (Status == TicketStatus.Closed)
|
||||
throw new DomainException("Тикет уже закрыт.");
|
||||
|
||||
Status = TicketStatus.Closed;
|
||||
}
|
||||
|
||||
/// <summary>Только из Resolved — Closed финален и не переоткрывается.</summary>
|
||||
public void Reopen()
|
||||
{
|
||||
if (Status != TicketStatus.Resolved)
|
||||
throw new DomainException("Переоткрыть можно только решённый тикет.");
|
||||
|
||||
Status = TicketStatus.Open;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user