fix: search existing SD ticket by CN (name) instead of email, with 3-match strategy
This commit is contained in:
+23
-7
@@ -209,13 +209,14 @@ async def _send_sd_api_request(
|
|||||||
return None
|
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' для пользователя.
|
Найти существующую открытую заявку с темой 'Запрос доступа к Trueconf' для пользователя.
|
||||||
|
Ищет по ФИО (name), затем по email, затем по системному имени с пометкой пользователя.
|
||||||
"""
|
"""
|
||||||
subject = "Запрос доступа к Trueconf"
|
subject = "Запрос доступа к Trueconf"
|
||||||
try:
|
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}
|
headers = {"TECHNICIAN_KEY": SD_TOKEN}
|
||||||
async with httpx.AsyncClient(verify=False) as client:
|
async with httpx.AsyncClient(verify=False) as client:
|
||||||
resp = await client.get(url, headers=headers, timeout=10.0)
|
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()
|
data = resp.json()
|
||||||
requests_list = data.get("requests", [])
|
requests_list = data.get("requests", [])
|
||||||
for req in requests_list:
|
for req in requests_list:
|
||||||
|
if subject not in req.get("subject", ""):
|
||||||
|
continue
|
||||||
requester = req.get("requester", {})
|
requester = req.get("requester", {})
|
||||||
req_email = requester.get("email", "") or requester.get("email_id", "")
|
# 1. Поиск по ФИО
|
||||||
if req_email == requester_email and subject in req.get("subject", ""):
|
req_name = requester.get("name", "") or requester.get("display_name", "")
|
||||||
|
if cn and cn in req_name:
|
||||||
ticket_id = req.get("id")
|
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)
|
return str(ticket_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to search existing tickets: {e}")
|
logger.warning(f"Failed to search existing tickets: {e}")
|
||||||
@@ -326,8 +342,8 @@ async def instruct_router_handler(msg: Message):
|
|||||||
else:
|
else:
|
||||||
# Нет доступа — проверяем, есть ли уже открытая заявка
|
# Нет доступа — проверяем, есть ли уже открытая заявка
|
||||||
ad_info = get_ad_user_info(user_id)
|
ad_info = get_ad_user_info(user_id)
|
||||||
requester_email = ad_info.get("mail") or DEFAULT_REQUESTER
|
requester_email = (ad_info.get("mail") if ad_info else None) or DEFAULT_REQUESTER
|
||||||
existing_ticket = await _find_existing_trueconf_ticket(requester_email)
|
existing_ticket = await _find_existing_trueconf_ticket(cn, requester_email)
|
||||||
if existing_ticket:
|
if existing_ticket:
|
||||||
# Заявка уже существует — показываем информацию
|
# Заявка уже существует — показываем информацию
|
||||||
set_state(user_id, "INSTRUCT_TRUECONF_VIEW")
|
set_state(user_id, "INSTRUCT_TRUECONF_VIEW")
|
||||||
|
|||||||
Reference in New Issue
Block a user