Files
site_aegisone/max_bot/app/handlers/inquiry.py
T

143 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.
"""
Обработчик заявок (inquiry).
Создаёт BotTicket с контактными данными пользователя,
отправляет уведомление на email, подтверждает пользователю.
"""
import datetime
import logging
from sqlalchemy import select
from app.database import async_session
from app.models import BotUser, BotConversation, BotMessage, BotTicket, BotTicketMessage, BotTicketStatus
from app.max_api import max_api
from app.settings_cache import settings_cache
from app.email_sender import email_sender
logger = logging.getLogger(__name__)
MOSCOW_TZ = datetime.timezone(datetime.timedelta(hours=3))
def moscow_now():
"""Возвращает текущее время в UTC+3 (Москва) без tzinfo."""
return datetime.datetime.now(MOSCOW_TZ).replace(tzinfo=None)
async def handle_inquiry(user_id: int, conv_id: int, text: str) -> None:
"""Обработка заявки: создаёт.ticket, отправляет email, подтверждает пользователю."""
async with async_session() as db:
result = await db.execute(
select(BotConversation).where(BotConversation.id == conv_id)
)
conv = result.scalar_one_or_none()
if not conv:
return
user_result = await db.execute(select(BotUser).where(BotUser.id == user_id))
user = user_result.scalar_one_or_none()
if not user:
await max_api.send_message(
user_id,
"Произошла ошибка при обработке запроса. Пожалуйста, попробуйте ещё раз позже.",
conversation_id=conv_id,
)
return
conv.inquiry_text = text
conv.state = "escalated"
await _finalize_ticket_in_tx(db, user_id, conv, user, text)
await db.commit()
async def _finalize_ticket_in_tx(
db,
user_id: int,
conv: BotConversation,
user: BotUser,
inquiry_text: str,
) -> None:
user_name = user.first_name or user.last_name or ""
ticket_title = f"Обращение от {user_name or 'клиента'} ({user_id})"
if len(inquiry_text) > 100:
ticket_title = inquiry_text[:97] + "..."
ticket = BotTicket(
user_id=user_id,
title=ticket_title,
description=inquiry_text,
priority="normal",
status="Новая",
created_by="bot",
contact_name=f"{user.first_name or ''} {user.last_name or ''}".strip() or None,
contact_phone=user.phone,
contact_email=user.email,
)
db.add(ticket)
await db.flush()
msg = BotTicketMessage(
ticket_id=ticket.id,
direction="incoming",
text=inquiry_text,
)
db.add(msg)
status_log = BotTicketStatus(
ticket_id=ticket.id,
new_status="Новая",
changed_by="bot",
)
db.add(status_log)
conv.state = "completed"
user.total_tickets = (user.total_tickets or 0) + 1
user_info = f"ID: {user_id}\nИмя: {user.first_name or 'не указано'} {user.last_name or ''}"
contact = user.phone or "не указан"
history = await _get_conversation_history(conv.id)
support_email = await settings_cache.get("support_email", "zakaz@aegisone.ru")
email_subject = await settings_cache.get(
"email_subject",
"Обращение через Виртуального помощника AegisOne Engineering",
)
import asyncio
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, lambda: email_sender.send_ticket_escalation(
to=support_email,
subject=email_subject,
user_info=user_info,
contact=contact,
inquiry=inquiry_text,
history=history,
))
await max_api.send_message(
user_id,
f"Зафиксировала: {inquiry_text}\n\n"
f"Ваша заявка отправлена инженеру. В ближайшее время он обязательно "
f"свяжется с вами.",
conversation_id=conv.id,
)
async def _get_conversation_history(conv_id: int) -> str:
async with async_session() as db:
result = await db.execute(
select(BotMessage)
.where(BotMessage.conversation_id == conv_id)
.order_by(BotMessage.id)
)
messages = result.scalars().all()
lines = []
for msg in messages:
direction = "Клиент" if msg.direction == "incoming" else "Бот"
time_str = msg.created_at.strftime("%d.%m.%Y %H:%M") if msg.created_at else ""
lines.append(f"[{time_str}] {direction}: {msg.text or ''}")
return "\n".join(lines)