192 lines
8.3 KiB
Python
192 lines
8.3 KiB
Python
"""
|
|
ORM-модели для PostgreSQL (SQLAlchemy 2.0).
|
|
|
|
Таблицы:
|
|
- bot_settings: настройки бота (ключ-значение)
|
|
- bot_features: фичи бота (вкл/выкл)
|
|
- bot_categories: категории базы знаний
|
|
- bot_knowledge_base: карточки базы знаний
|
|
- bot_users: пользователи бота (контакты, согласие)
|
|
- bot_conversations: диалоги (state machine)
|
|
- bot_messages: сообщения (incoming/outgoing)
|
|
- bot_tickets: заявки
|
|
- bot_ticket_messages: сообщения заявок
|
|
- bot_processing_logs: логи обработки
|
|
- bot_ticket_statuses: история смены статусов заявок
|
|
- bot_unknown_questions: неизвестные вопросы (автогенерация KB)
|
|
"""
|
|
from __future__ import annotations
|
|
import datetime
|
|
from sqlalchemy import Column, Integer, BigInteger, String, Text, Boolean, DateTime, ForeignKey, ARRAY
|
|
from sqlalchemy.orm import DeclarativeBase, relationship
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
pass
|
|
|
|
|
|
class BotSetting(Base):
|
|
__tablename__ = "bot_settings"
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
key = Column(String(255), unique=True, nullable=False)
|
|
value = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
|
|
|
|
|
class BotFeature(Base):
|
|
__tablename__ = "bot_features"
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
key = Column(String(255), unique=True, nullable=False)
|
|
name = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
is_enabled = Column(Boolean, default=False)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
|
|
class BotCategory(Base):
|
|
__tablename__ = "bot_categories"
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
name = Column(String(255), nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
sort_order = Column(Integer, default=0)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
|
|
class BotKnowledgeBase(Base):
|
|
__tablename__ = "bot_knowledge_base"
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
category_id = Column(Integer, ForeignKey("bot_categories.id"), nullable=True)
|
|
question = Column(Text, nullable=False)
|
|
answer = Column(Text, nullable=True)
|
|
keywords = Column(ARRAY(String), nullable=True)
|
|
is_active = Column(Boolean, default=True)
|
|
source_url = Column(String(500), nullable=True)
|
|
sort_order = Column(Integer, default=0)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
|
|
|
category = relationship("BotCategory", lazy="joined")
|
|
|
|
|
|
class BotUser(Base):
|
|
"""Пользователь бота: профиль, контакты, согласие на обработку ПД."""
|
|
__tablename__ = "bot_users"
|
|
id = Column(BigInteger, primary_key=True)
|
|
first_name = Column(String(255), nullable=True)
|
|
last_name = Column(String(255), nullable=True)
|
|
patronymic = Column(String(255), nullable=True)
|
|
username = Column(String(255), nullable=True)
|
|
phone = Column(String(50), nullable=True)
|
|
email = Column(String(255), nullable=True)
|
|
organization = Column(String(255), nullable=True)
|
|
address = Column(Text, nullable=True)
|
|
vcf_raw = Column(Text, nullable=True)
|
|
contact_hash = Column(String(255), nullable=True)
|
|
phone_verified = Column(Boolean, default=False)
|
|
email_verified = Column(Boolean, default=False)
|
|
consent_given = Column(Boolean, default=False)
|
|
consent_date = Column(DateTime, nullable=True)
|
|
consent_revoked_date = Column(DateTime, nullable=True)
|
|
last_interaction = Column(DateTime, nullable=True)
|
|
total_conversations = Column(Integer, default=0)
|
|
total_tickets = Column(Integer, default=0)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
|
|
|
|
|
class BotConversation(Base):
|
|
__tablename__ = "bot_conversations"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
user_id = Column(BigInteger, ForeignKey("bot_users.id"), nullable=False)
|
|
state = Column(String(50), default="greeting")
|
|
intent = Column(String(50), nullable=True)
|
|
inquiry_text = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
|
|
|
user = relationship("BotUser", lazy="joined")
|
|
|
|
|
|
class BotMessage(Base):
|
|
__tablename__ = "bot_messages"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
conversation_id = Column(BigInteger, ForeignKey("bot_conversations.id", ondelete="CASCADE"), nullable=False)
|
|
direction = Column(String(10), nullable=False)
|
|
text = Column(Text, nullable=True)
|
|
attachment_json = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
conversation = relationship("BotConversation", lazy="joined")
|
|
|
|
|
|
class BotTicket(Base):
|
|
__tablename__ = "bot_tickets"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
user_id = Column(BigInteger, ForeignKey("bot_users.id"), nullable=False)
|
|
title = Column(String(500), nullable=True)
|
|
description = Column(Text, nullable=True)
|
|
priority = Column(String(20), default="normal")
|
|
status = Column(String(20), default="Новая")
|
|
created_by = Column(String(100), default="bot")
|
|
assigned_to = Column(BigInteger, nullable=True)
|
|
contact_name = Column(String(500), nullable=True)
|
|
contact_phone = Column(String(50), nullable=True)
|
|
contact_email = Column(String(255), nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
|
|
|
|
user = relationship("BotUser", lazy="joined")
|
|
|
|
|
|
class BotTicketMessage(Base):
|
|
__tablename__ = "bot_ticket_messages"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
ticket_id = Column(BigInteger, ForeignKey("bot_tickets.id"), nullable=False)
|
|
direction = Column(String(10), nullable=False)
|
|
text = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
ticket = relationship("BotTicket", lazy="joined")
|
|
|
|
|
|
class BotProcessingLog(Base):
|
|
__tablename__ = "bot_processing_logs"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
user_id = Column(BigInteger, ForeignKey("bot_users.id"), nullable=False)
|
|
conversation_id = Column(BigInteger, ForeignKey("bot_conversations.id", ondelete="CASCADE"), nullable=True)
|
|
step = Column(String(50), nullable=False)
|
|
status = Column(String(20), default="ok")
|
|
message = Column(Text, nullable=True)
|
|
detail = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
user = relationship("BotUser", lazy="joined")
|
|
|
|
|
|
class BotTicketStatus(Base):
|
|
__tablename__ = "bot_ticket_statuses"
|
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
|
ticket_id = Column(BigInteger, ForeignKey("bot_tickets.id"), nullable=False)
|
|
old_status = Column(String(20), nullable=True)
|
|
new_status = Column(String(20), nullable=False)
|
|
changed_by = Column(String(100), nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
ticket = relationship("BotTicket", lazy="joined")
|
|
|
|
|
|
class BotUnknownQuestion(Base):
|
|
__tablename__ = "bot_unknown_questions"
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
question_text = Column(Text, nullable=False)
|
|
normalized_text = Column(Text, nullable=True)
|
|
ask_count = Column(Integer, default=1)
|
|
user_ids = Column(ARRAY(BigInteger), default=[])
|
|
status = Column(String(50), default="new")
|
|
generated_answer = Column(Text, nullable=True)
|
|
generated_keywords = Column(ARRAY(String), nullable=True)
|
|
generated_category_id = Column(Integer, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
reviewed_at = Column(DateTime, nullable=True)
|