167 lines
5.6 KiB
Python
167 lines
5.6 KiB
Python
"""
|
||
Обработчики просмотра заявок (Intradesk).
|
||
|
||
Навигация через callback payload — все переходы редактируют текущее сообщение:
|
||
"view_tickets" → список, страница 0
|
||
"itickets_page:{n}" → список, страница n
|
||
"iticket_detail:{id}" → карточка задачи
|
||
"main_menu" → в menu.py
|
||
"""
|
||
import re
|
||
|
||
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 intradesk_tasks_list_kb, iticket_detail_kb
|
||
from bot.send_helper import bot_reply
|
||
from database.connection import get_db
|
||
from database.queries.intradesk import (
|
||
count_tasks_for_local_org,
|
||
get_task_for_local_org,
|
||
get_tasks_for_local_org,
|
||
)
|
||
from external.intradesk_api import get_task_last_comment
|
||
|
||
router = Router(router_id="view_tickets")
|
||
|
||
_PAGE_SIZE = 8
|
||
|
||
|
||
def _status_icon(status_name: str) -> str:
|
||
sn = status_name.lower()
|
||
if "выполнен" in sn:
|
||
return "🟢"
|
||
if "работ" in sn:
|
||
return "🟡"
|
||
if "открыт" in sn:
|
||
return "🔴"
|
||
return "⚪"
|
||
|
||
|
||
def _priority_icon(priority_name: str) -> str:
|
||
pn = priority_name.lower()
|
||
if "критич" in pn:
|
||
return "🔴"
|
||
if "высок" in pn:
|
||
return "🟠"
|
||
if "средн" in pn:
|
||
return "🟡"
|
||
return "⚪"
|
||
|
||
|
||
async def _tasks_page_text(org_id: int, page: int) -> tuple[str, list[dict], int]:
|
||
"""Возвращает (текст, задачи, всего)."""
|
||
db = get_db()
|
||
tasks = await get_tasks_for_local_org(db, org_id, page=page, page_size=_PAGE_SIZE)
|
||
total = await count_tasks_for_local_org(db, org_id)
|
||
if not tasks:
|
||
return "📭 У вашей организации пока нет заявок.", [], 0
|
||
pages = max(1, -(-total // _PAGE_SIZE))
|
||
text = f"📋 Заявки — стр. {page + 1} из {pages} (всего: {total}):"
|
||
return text, tasks, 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="")
|
||
text, tasks, total = await _tasks_page_text(bot_user["org_id"], 0)
|
||
kb = intradesk_tasks_list_kb(tasks, page=0, total=total) if tasks else None
|
||
await bot_reply(
|
||
event,
|
||
text=text,
|
||
attachments=[kb] if kb else None,
|
||
user_id=bot_user["max_user_id"],
|
||
chat_id=event.message.recipient.chat_id if event.message else None,
|
||
)
|
||
|
||
|
||
@router.message_callback(PayloadStartsWith("itickets_page:"))
|
||
async def cb_itickets_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
|
||
text, tasks, total = await _tasks_page_text(bot_user["org_id"], page)
|
||
kb = intradesk_tasks_list_kb(tasks, page=page, total=total) if tasks else None
|
||
await bot_reply(
|
||
event,
|
||
text=text,
|
||
attachments=[kb] if kb else None,
|
||
user_id=bot_user["max_user_id"],
|
||
chat_id=event.message.recipient.chat_id if event.message else None,
|
||
)
|
||
|
||
|
||
@router.message_callback(PayloadStartsWith("iticket_detail:"))
|
||
async def cb_iticket_detail(
|
||
event: MessageCallback, context: BaseContext, bot_user: dict
|
||
) -> None:
|
||
try:
|
||
task_id = int(event.callback.payload.split(":")[1])
|
||
except (IndexError, ValueError):
|
||
await event.answer(notification="Ошибка")
|
||
return
|
||
|
||
db = get_db()
|
||
task = await get_task_for_local_org(db, task_id, bot_user["org_id"])
|
||
|
||
if task is None:
|
||
await event.answer(notification="Нет доступа")
|
||
return
|
||
|
||
await event.answer(notification="")
|
||
|
||
sicon = _status_icon(task.get("status_name") or "")
|
||
picon = _priority_icon(task.get("priority_name") or "")
|
||
|
||
num = task.get("task_number") or task["id"]
|
||
lines = [
|
||
f"📌 Заявка #{num}",
|
||
f"Статус: {sicon} {task.get('status_name') or '—'}",
|
||
f"Приоритет: {picon} {task.get('priority_name') or '—'}",
|
||
]
|
||
if task.get("service_name"):
|
||
lines.append(f"Сервис: {task['service_name']}")
|
||
if task.get("executor_name"):
|
||
lines.append(f"Исполнитель: {task['executor_name']}")
|
||
lines.append(f"Создана: {(task.get('created_at') or '')[:10] or '—'}")
|
||
lines.append(f"Обновлена: {(task.get('updated_at') or '')[:10] or '—'}")
|
||
|
||
if task.get("name"):
|
||
lines += ["", f"📄 {task['name']}"]
|
||
|
||
if task.get("description"):
|
||
desc = re.sub(r"<[^>]+>", "", task["description"]).strip()
|
||
if desc:
|
||
if len(desc) > 800:
|
||
desc = desc[:800] + "…"
|
||
lines += ["", f"💬 {desc}"]
|
||
|
||
# Последний комментарий — запрашиваем из Intradesk API
|
||
comment = await get_task_last_comment(task["id"])
|
||
if comment and comment.get("text"):
|
||
ctext = comment["text"]
|
||
if len(ctext) > 500:
|
||
ctext = ctext[:500] + "…"
|
||
lines += [
|
||
"",
|
||
f"💭 Последний комментарий ({comment['date']}):",
|
||
f" {ctext}",
|
||
f" — {comment['author']}",
|
||
]
|
||
|
||
await bot_reply(
|
||
event,
|
||
text="\n".join(lines),
|
||
attachments=[iticket_detail_kb()],
|
||
user_id=bot_user["max_user_id"],
|
||
chat_id=event.message.recipient.chat_id if event.message else None,
|
||
)
|