intra_max_chatbot/bot/handlers/view_tickets.py
2026-03-26 00:54:10 +03:00

141 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Обработчики просмотра заявок.
Навигация полностью через callback payload — FSM-состояния не нужны.
"view_tickets" → список, страница 0
"tickets_page:{n}" → список, страница n
"ticket_detail:{id}" → карточка заявки
"main_menu" → в menu.py
"""
from maxapi.context import BaseContext
from maxapi.dispatcher import Router
from maxapi.filters import F
from maxapi.types.updates.message_callback import MessageCallback
from bot.filters import PayloadStartsWith
from bot.keyboards import ticket_detail_kb, tickets_list_kb
from bot.send_helper import bot_send
from database.queries.ticket_attachments import get_attachments
from database.queries.tickets import (
PAGE_SIZE,
count_tickets_for_org,
get_ticket,
get_tickets_for_org,
)
router = Router(router_id="view_tickets")
STATUS_LABELS = {
"open": "🔴 Открыта",
"in_progress": "🟡 В работе",
"closed": "🟢 Закрыта",
}
async def _send_tickets_page(
event: MessageCallback, page: int, bot_user: dict
) -> None:
org_id = bot_user["org_id"]
tickets = await get_tickets_for_org(org_id, page=page)
total = await count_tickets_for_org(org_id)
chat_id = event.message.recipient.chat_id if event.message else None
if chat_id is None:
return
if not tickets:
await bot_send(
event.bot,
chat_id=chat_id,
user_id=bot_user["max_user_id"],
text="📭 У вашей организации пока нет заявок.",
attachments=[ticket_detail_kb(page=0)],
)
return
await bot_send(
event.bot,
chat_id=chat_id,
user_id=bot_user["max_user_id"],
text=f"📋 Заявки организации (стр. {page + 1}):",
attachments=[tickets_list_kb(tickets, page=page, total=total)],
)
@router.message_callback(F.callback.payload == "view_tickets")
async def cb_view_tickets(
event: MessageCallback, context: BaseContext, bot_user: dict
) -> None:
await event.answer(notification="")
await _send_tickets_page(event, page=0, bot_user=bot_user)
@router.message_callback(PayloadStartsWith("tickets_page:"))
async def cb_tickets_page(
event: MessageCallback, context: BaseContext, bot_user: dict
) -> None:
await event.answer(notification="")
try:
page = int(event.callback.payload.split(":")[1])
except (IndexError, ValueError):
page = 0
await _send_tickets_page(event, page=page, bot_user=bot_user)
@router.message_callback(PayloadStartsWith("ticket_detail:"))
async def cb_ticket_detail(
event: MessageCallback, context: BaseContext, bot_user: dict
) -> None:
try:
ticket_id = int(event.callback.payload.split(":")[1])
except (IndexError, ValueError):
await event.answer(notification="Ошибка")
return
ticket = await get_ticket(ticket_id)
chat_id = event.message.recipient.chat_id if event.message else None
if chat_id is None:
return
# Проверка доступа: заявка должна принадлежать той же организации
if ticket is None or ticket["org_id"] != bot_user["org_id"]:
await event.answer(notification="Нет доступа")
return
await event.answer(notification="")
status_label = STATUS_LABELS.get(ticket["status"], ticket["status"])
text = (
f"📌 Заявка #{ticket['id']}\n"
f"Статус: {status_label}\n"
f"Создана: {ticket['created_at'][:16]}\n\n"
f"📄 Описание:\n{ticket['description']}"
)
if ticket.get("last_comment"):
text += f"\n\n💬 Последний комментарий:\n{ticket['last_comment']}"
# Вложения
attachments = await get_attachments(ticket_id)
if attachments:
att_lines = []
for a in attachments:
icon = {
"AttachmentType.IMAGE": "🖼",
"AttachmentType.VIDEO": "🎬",
"AttachmentType.AUDIO": "🎙",
"AttachmentType.FILE": "📎",
}.get(a["attachment_type"], "📎")
line = f"{icon} {a['attachment_type'].split('.')[-1].capitalize()}"
if a.get("attachment_url"):
line += f": {a['attachment_url']}"
att_lines.append(line)
text += "\n\n📎 Вложения:\n" + "\n".join(att_lines)
await bot_send(
event.bot,
chat_id=chat_id,
user_id=bot_user["max_user_id"],
text=text,
attachments=[ticket_detail_kb(page=0)],
)