156 lines
6.7 KiB
Python
156 lines
6.7 KiB
Python
from app.settings_cache import SettingsCache
|
|
from app.conversation import get_or_create_user, get_template_rendered
|
|
from app.fsm import BotState, FSM
|
|
from app.keyboards.inline import build_main_menu_buttons
|
|
|
|
|
|
async def handle_sla_ticket(bot, user_data: dict, db, max_api):
|
|
max_user_id = user_data["user_id"]
|
|
text = user_data.get("text", "").strip()
|
|
|
|
if FSM.get_state(max_user_id) != BotState.SLA_TICKET_CREATE:
|
|
FSM.set_state(max_user_id, BotState.SLA_TICKET_CREATE)
|
|
await max_api.send_message(max_user_id, "🔧 **Заявка по SLA**\n\nПроверяю ваш SLA контракт...")
|
|
|
|
user = await get_or_create_user(db, max_user_id)
|
|
phone = user.phone or ""
|
|
if not phone:
|
|
await max_api.send_message(max_user_id, "Не могу найти ваш номер телефона. Укажите его, пожалуйста.")
|
|
return
|
|
|
|
from sqlalchemy import select
|
|
from app.models.models import Customer, Object, SLAContract
|
|
result = await db.execute(
|
|
select(Customer).where(Customer.contact_phone.ilike(f"%{phone[-10:]}%")).limit(1)
|
|
)
|
|
customer = result.scalar_one_or_none()
|
|
if not customer:
|
|
await _send_no_sla(bot, user_data, db, max_api)
|
|
return
|
|
|
|
result = await db.execute(
|
|
select(Object).where(Object.customer_id == customer.id, Object.status == "active").limit(1)
|
|
)
|
|
obj = result.scalar_one_or_none()
|
|
if not obj:
|
|
await _send_no_sla(bot, user_data, db, max_api)
|
|
return
|
|
|
|
result = await db.execute(
|
|
select(SLAContract).where(
|
|
SLAContract.object_id == obj.id,
|
|
SLAContract.status == "active"
|
|
).order_by(SLAContract.created_at.desc()).limit(1)
|
|
)
|
|
sla = result.scalar_one_or_none()
|
|
if not sla:
|
|
await _send_no_sla(bot, user_data, db, max_api)
|
|
return
|
|
|
|
level_map = {"start": "Базовый", "business": "Оптимальный", "enterprise": "Максимальный"}
|
|
text = await get_template_rendered(db, "sla_ticket_found",
|
|
object_name=obj.name,
|
|
service_level=level_map.get(sla.service_level, sla.service_level))
|
|
await max_api.send_message(max_user_id, text, format="markdown")
|
|
return
|
|
|
|
if not text:
|
|
await max_api.send_message(max_user_id, "Опишите неисправность. Вы можете прикрепить фото или документ.")
|
|
return
|
|
|
|
user = await get_or_create_user(db, max_user_id)
|
|
|
|
from sqlalchemy import select, func
|
|
from app.models.models import Customer, Object, SLAContract, BotTicket
|
|
result = await db.execute(
|
|
select(Customer).where(Customer.contact_phone.ilike(f"%{user.phone[-10:]}%")).limit(1)
|
|
)
|
|
customer = result.scalar_one_or_none()
|
|
obj = None
|
|
sla = None
|
|
if customer:
|
|
result = await db.execute(
|
|
select(Object).where(Object.customer_id == customer.id, Object.status == "active").limit(1)
|
|
)
|
|
obj = result.scalar_one_or_none()
|
|
if obj:
|
|
result = await db.execute(
|
|
select(SLAContract).where(
|
|
SLAContract.object_id == obj.id, SLAContract.status == "active"
|
|
).order_by(SLAContract.created_at.desc()).limit(1)
|
|
)
|
|
sla = result.scalar_one_or_none()
|
|
|
|
priority_map = {"start": "low", "business": "normal", "enterprise": "high"}
|
|
response_map = {"start": "4 часа", "business": "2 часа", "enterprise": "30 минут"}
|
|
sla_level = sla.service_level if sla else "start"
|
|
priority = priority_map.get(sla_level, "normal")
|
|
|
|
result = await db.execute(select(func.count(BotTicket.id)))
|
|
ticket_num = f"T-{result.scalar() + 1:04d}"
|
|
|
|
from app.models.models import BotTicket, BotTicketMessage, BotTicketStatus
|
|
ticket = BotTicket(
|
|
ticket_number=ticket_num,
|
|
user_id=user.id,
|
|
object_id=obj.id if obj else None,
|
|
customer_id=customer.id if customer else None,
|
|
title=text[:100],
|
|
description=text,
|
|
priority=priority,
|
|
status="open",
|
|
created_by="bot",
|
|
sla_contract_id=sla.id if sla else None,
|
|
has_attachment=user_data.get("has_attachment", False),
|
|
attachment_type=user_data.get("attachment_type", ""),
|
|
attachment_path=user_data.get("attachment_path", ""),
|
|
)
|
|
db.add(ticket)
|
|
await db.flush()
|
|
|
|
db.add(BotTicketMessage(ticket_id=ticket.id, direction="in", text=text, sender="client"))
|
|
db.add(BotTicketStatus(ticket_id=ticket.id, old_status="", new_status="open", changed_by="bot"))
|
|
await db.flush()
|
|
|
|
has_attachment = user_data.get("has_attachment", False)
|
|
attachment_type = user_data.get("attachment_type", "")
|
|
attachment_path = user_data.get("attachment_path", "")
|
|
if has_attachment:
|
|
ticket.has_attachment = True
|
|
ticket.attachment_type = attachment_type
|
|
ticket.attachment_path = attachment_path
|
|
await db.flush()
|
|
|
|
text = await get_template_rendered(db, "sla_ticket_created",
|
|
ticket_number=ticket_num,
|
|
priority=priority,
|
|
response_time=response_map.get(sla_level, "2 часа"))
|
|
await max_api.send_message(max_user_id, text, format="markdown")
|
|
|
|
from app.max_notifications import notify_ticket_created as nt
|
|
await nt(db, ticket, max_api)
|
|
|
|
FSM.transition(max_user_id, "done")
|
|
buttons = build_main_menu_buttons()
|
|
menu_text = await get_template_rendered(db, "main_menu")
|
|
await max_api.send_message_with_keyboard(max_user_id, menu_text, buttons)
|
|
|
|
|
|
async def _send_no_sla(bot, user_data, db, max_api):
|
|
max_user_id = user_data["user_id"]
|
|
await SettingsCache.refresh(db)
|
|
phone_1 = SettingsCache.get("phone_1")
|
|
phone_2 = SettingsCache.get("phone_2")
|
|
email = SettingsCache.get("support_email")
|
|
text = await get_template_rendered(db, "sla_ticket_not_found",
|
|
phone_1=phone_1, phone_2=phone_2,
|
|
support_email=email)
|
|
from app.keyboards.inline import build_phone_email_buttons
|
|
subject = SettingsCache.get("email_subject")
|
|
buttons = build_phone_email_buttons(phone_1, phone_2, email, subject)
|
|
await max_api.send_message_with_keyboard(max_user_id, text, buttons, format="markdown")
|
|
FSM.transition(max_user_id, "done")
|
|
buttons = build_main_menu_buttons()
|
|
menu_text = await get_template_rendered(db, "main_menu")
|
|
await max_api.send_message_with_keyboard(max_user_id, menu_text, buttons)
|