""" Обработчики просмотра заявок (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, menu_only_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 menu_only_kb() await bot_reply( event, text=text, attachments=[kb], 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 menu_only_kb() await bot_reply( event, text=text, attachments=[kb], 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, )