133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
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():
|
||
return datetime.datetime.now(MOSCOW_TZ).replace(tzinfo=None)
|
||
|
||
|
||
async def handle_inquiry(user_id: int, conv_id: int, text: str) -> None:
|
||
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,
|
||
"Произошла ошибка при обработке запроса. Пожалуйста, попробуйте ещё раз позже.",
|
||
)
|
||
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"свяжется с вами.",
|
||
)
|
||
|
||
|
||
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)
|