support-tickets
Тикеты поддержки: эскалация из FAQ, ответы оператора, оценка качества, Telegram-уведомления
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: IntegerFieldAPI — пользовательский
| Метод | Путь | Описание |
|---|
|-------|------|----------|
| 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** — настроить шаблон и задержку уведомлений.