Files
site_aegisone/max_bot/app/models.py
T
angel 72b6879f4b v1.7.0: refactor max_bot to flat structure, add VCF+UserModel+NLP history context, portal pages and proxy fixes
- Refactored max_bot from nested packages to flat module structure
- Q2: Extended BotUser model (patronymic, email, org, address, vcf_raw, contact_hash, phone_verified, email_verified, last_interaction, total_conversations, total_tickets)
- Q2: VCF parser (FN, N, TEL, EMAIL, ORG, ADR), upsert on re-contact, NLP history context (_get_user_history_context -> YandexGPT)
- Q1: Broadcast preview modal with 10s confirmation timer
- Q3: CSS var(--white)->var(--bg-card), var(--text)->var(--text-primary)
- Q4: bot_settings showNotification(), editable max_bot_id
- Q5: Webhook secret passthrough via X-Max-Bot-Api-Secret
- Masking sensitive keys, dialog_cleared handler, migrate via _add_column_if_not_exists()
- Rate limit (asyncio.sleep 0.5 per 10), dead code removed, conv.intent context in contact.py
- Portal pages: bot_consent, bot_kb (edit), bot_settings, bot_test, bot_tickets, portal_settings
- Tests: 21/21 passing, added test_yandex_gpt.py, test_email_sender.py
- Deploy: deploy_full.sh, schema.sql, seed_knowledge_base.sql
2026-05-29 02:30:30 +03:00

141 lines
5.8 KiB
Python

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)
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"), 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)
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 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")