support-tickets

Тикеты поддержки: эскалация из FAQ, ответы оператора, оценка качества, Telegram-уведомления

Business
Source: ДобинДом
Files: 6
Stack:
DjangoDRFReactTanStack Query

Specification

support-tickets

Назначение

Система тикетов поддержки: пользователь создаёт обращение (эскалация из AI FAQ или напрямую), оператор отвечает через админ-панель, после закрытия — оценка качества. Три слоя: backend API, пользовательский фронтенд, админ-панель.

Контракты

Модели данных

class SupportTicket:
    user: ForeignKey(User)
    status: CharField  # 'open' | 'in_progress' | 'resolved'
    assigned_operator: CharField(100)
    resolved_at: DateTimeField(null=True)
    user_last_read_at: DateTimeField(null=True)

class SupportMessage:
    ticket: ForeignKey(SupportTicket)
    sender_type: CharField  # 'user' | 'operator' | 'ai'
    text: TextField
    image: ImageField(null=True)  # до 10 МБ

class SupportRating:
    ticket: OneToOneField(SupportTicket)
    stars: PositiveSmallIntegerField  # 1-5
    comment: TextField

class SupportSettings(Singleton):
    email_notify_delay_minutes: PositiveIntegerField  # default: 10

class FAQEntry:
    question: TextField
    answer: TextField
    category: CharField  # 'О проекте', 'Подписка', 'Оплата', etc.
    is_active: BooleanField
    sort_order: IntegerField

API — пользовательский

МетодПутьОписание

|-------|------|----------|

POST/support/escalate/Создать тикет (эскалация из FAQ)
GET/support/ticket/messages/Сообщения тикета
POST/support/ticket/messages/Отправить сообщение (text + image)
POST/support/ticket/rating/Оценить закрытый тикет (1-5 звёзд)
POST/support/ticket/read/Пометить тикет прочитанным

API — админ-панель

МетодПутьОписание

|-------|------|----------|

GET/admin/support/tickets/Список тикетов (фильтр по статусу)
POST/admin/support/tickets/{id}/reply/Ответ оператора (text + image)
POST/admin/support/tickets/{id}/resolve/Закрыть тикет
POST/admin/support/tickets/{id}/typing/Сигнал «оператор печатает» (Redis TTL 6s)
GET/admin/support/count/Счётчик открытых тикетов (для badge)
GET/PATCH/admin/support/settings/Настройки поддержки
GET/admin/support/ratings/Статистика оценок (avg, distribution, recent)

Frontend hooks (React Query)

// Пользовательский фронтенд
useSupportTicket(pollInSupport?: boolean): SupportTicket | null
useSupportMessages(enabled: boolean): SupportMessage[]
markTicketRead(): void

// Админ-панель
useSupportTickets(filters): SupportTicket[]
useSupportTicketDetail(id): SupportTicketDetail
useReplyToTicket(): mutation
useResolveTicket(): mutation
useSupportRatingStats(): RatingStats
useSupportTicketCount(): { count: number }
useSupportSettings(): SupportSettingsData
useUpdateSupportSettings(): mutation
sendTypingPing(ticketId): void

Уведомления

**Telegram** — при создании тикета: уведомление операторам с telegram_id и доступом к разделу support
**Email** — при ответе оператора: отложенное email-уведомление (настраиваемая задержка через SupportSettings)

Real-time

Polling: пользователь — 4-5 сек, админ — 4-5 сек, badge — 15 сек
Typing indicator: Redis key с TTL 6 сек (`support_typing:{ticket_id}`)

Зависимости

Django + DRF
Redis (typing indicator)
Celery/Huey (отложенные email-уведомления)
django-solo (singleton settings)
React + TanStack Query (фронтенд)

Реализации

СтекПутьИсточникСтатус

|------|------|----------|--------|

Django + React (TypeScript)implementations/django-react/ДобинДомпроверен

Адаптация

**Модель User** — заменить связь `user` на свою модель пользователя.
**Уведомления** — заменить Telegram на свой канал (Slack, webhook, push).
**FAQ** — опционально: убрать эскалацию из AI FAQ, если нет AI-чата.
**Файлы** — изменить `upload_to` путь для вложений.
**Permissions** — заменить `IsUser` / `IsStaffUser` на свою систему прав.
**Email** — настроить шаблон и задержку уведомлений.