diff --git a/instruct/handlers.py b/instruct/handlers.py index 77278cb..98c5418 100644 --- a/instruct/handlers.py +++ b/instruct/handlers.py @@ -209,13 +209,14 @@ async def _send_sd_api_request( return None -async def _find_existing_trueconf_ticket(requester_email: str) -> str | None: +async def _find_existing_trueconf_ticket(cn: str, requester_email: str = None) -> str | None: """ Найти существующую открытую заявку с темой 'Запрос доступа к Trueconf' для пользователя. + Ищет по ФИО (name), затем по email, затем по системному имени с пометкой пользователя. """ subject = "Запрос доступа к Trueconf" try: - url = f"{SD_URL.rstrip('/')}/api/v3/requests?filter=status:Open&fields=id,subject,requester" + url = f"{SD_URL.rstrip('/')}/api/v3/requests?filter=status:Open&fields=id,subject,requester,description" headers = {"TECHNICIAN_KEY": SD_TOKEN} async with httpx.AsyncClient(verify=False) as client: resp = await client.get(url, headers=headers, timeout=10.0) @@ -223,11 +224,26 @@ async def _find_existing_trueconf_ticket(requester_email: str) -> str | None: data = resp.json() requests_list = data.get("requests", []) for req in requests_list: + if subject not in req.get("subject", ""): + continue requester = req.get("requester", {}) - req_email = requester.get("email", "") or requester.get("email_id", "") - if req_email == requester_email and subject in req.get("subject", ""): + # 1. Поиск по ФИО + req_name = requester.get("name", "") or requester.get("display_name", "") + if cn and cn in req_name: ticket_id = req.get("id") - logger.info(f"Found existing Trueconf ticket #{ticket_id} for {requester_email}") + logger.info(f"Found existing Trueconf ticket #{ticket_id} for CN={cn} (by name)") + return str(ticket_id) + # 2. Поиск по email + req_email = requester.get("email", "") or requester.get("email_id", "") + if req_email == requester_email and requester_email and requester_email not in (DEFAULT_REQUESTER, "ai@sibcem.ru"): + ticket_id = req.get("id") + logger.info(f"Found existing Trueconf ticket #{ticket_id} for {requester_email} (by email)") + return str(ticket_id) + # 3. Поиск по системному заявщику с пометкой пользователя в описании + req_desc = req.get("description", "") or "" + if f"[Пользователь: {cn}]" in req_desc: + ticket_id = req.get("id") + logger.info(f"Found existing Trueconf ticket #{ticket_id} for CN={cn} (by description note)") return str(ticket_id) except Exception as e: logger.warning(f"Failed to search existing tickets: {e}") @@ -326,8 +342,8 @@ async def instruct_router_handler(msg: Message): else: # Нет доступа — проверяем, есть ли уже открытая заявка ad_info = get_ad_user_info(user_id) - requester_email = ad_info.get("mail") or DEFAULT_REQUESTER - existing_ticket = await _find_existing_trueconf_ticket(requester_email) + requester_email = (ad_info.get("mail") if ad_info else None) or DEFAULT_REQUESTER + existing_ticket = await _find_existing_trueconf_ticket(cn, requester_email) if existing_ticket: # Заявка уже существует — показываем информацию set_state(user_id, "INSTRUCT_TRUECONF_VIEW")