feat: creating chats for cards and clients, sending and deleting text messages

This commit is contained in:
2025-03-27 15:13:10 +04:00
parent a466e46f28
commit 2cdccb33ca
25 changed files with 928 additions and 7 deletions

View File

@@ -23,5 +23,6 @@ from .card_group import *
from .transaction import *
from .residues import *
from .shipping import *
from .chat import *
configure_mappers()

View File

@@ -10,7 +10,7 @@ from models.work_shifts import WorkShift
if TYPE_CHECKING:
from models.payroll import PayRate, PaymentRecord
from models import Card, CardEmployees
from models import Card, CardEmployees, Message
role_permissions = Table(
'role_permissions',
@@ -138,6 +138,12 @@ class User(BaseModel):
lazy="noload",
)
messages: Mapped[list['Message']] = relationship(
'Message',
back_populates='crm_sender',
lazy='noload',
)
class InviteCode(BaseModel):
__tablename__ = 'invite_codes'

View File

@@ -12,8 +12,8 @@ from .shipping_warehouse import ShippingWarehouse
if TYPE_CHECKING:
from . import (
CardBillRequest, User, BaseModel, Board, CardStatus, CardGroup, CardAttribute, Client, CardTag,
CardService as CardServiceModel, CardProduct,
)
CardService as CardServiceModel, CardProduct, Chat,
)
class Card(BaseModel):
@@ -114,6 +114,9 @@ class Card(BaseModel):
# module employees
employees: Mapped[list['CardEmployees']] = relationship(back_populates='card', lazy='selectin')
# module chat
chat: Mapped[Optional['Chat']] = relationship(back_populates='card', lazy='joined')
# endregion

154
models/chat.py Normal file
View File

@@ -0,0 +1,154 @@
import enum
from datetime import datetime
from typing import Optional, TYPE_CHECKING
from uuid import UUID
from sqlalchemy import ForeignKey, BigInteger, Enum, Uuid
from sqlalchemy.orm import Mapped, mapped_column, relationship
from models import BaseModel, User
if TYPE_CHECKING:
from models import Client, Card
class TgUser(BaseModel):
__tablename__ = 'tg_users'
id: Mapped[int] = mapped_column(
BigInteger(),
primary_key=True,
comment='Telegram user ID',
)
username: Mapped[str] = mapped_column(
index=True,
nullable=False,
unique=True,
)
first_name: Mapped[str] = mapped_column(nullable=True)
last_name: Mapped[str] = mapped_column(nullable=True)
messages: Mapped['Message'] = relationship(
'Message',
lazy='noload',
back_populates='tg_sender',
)
class TgGroup(BaseModel):
__tablename__ = 'tg_groups'
id: Mapped[UUID] = mapped_column(Uuid, primary_key=True)
tg_group_id: Mapped[int] = mapped_column(
BigInteger(),
nullable=False,
unique=True,
)
tg_invite_link: Mapped[str] = mapped_column(nullable=False)
client_id: Mapped[Optional[int]] = mapped_column(
ForeignKey('clients.id'),
unique=True,
)
client: Mapped[Optional['Client']] = relationship(
'Client',
lazy='joined',
back_populates='tg_group',
)
chats: Mapped[list['Chat']] = relationship(
'Chat',
lazy='noload',
back_populates='tg_group',
)
class Chat(BaseModel):
__tablename__ = 'chats'
id: Mapped[int] = mapped_column(primary_key=True)
tg_topic_id: Mapped[int] = mapped_column(nullable=False)
card_id: Mapped[Optional[int]] = mapped_column(
ForeignKey('cards.id'),
unique=True,
)
card: Mapped[Optional['Card']] = relationship(
'Card',
lazy='joined',
back_populates='chat',
)
client_id: Mapped[Optional[int]] = mapped_column(
ForeignKey('clients.id'),
unique=True,
)
client: Mapped[Optional['Client']] = relationship(
'Client',
lazy='joined',
back_populates='chat',
)
tg_group_id: Mapped[UUID] = mapped_column(
ForeignKey('tg_groups.id'),
nullable=False,
)
tg_group: Mapped[TgGroup] = relationship(
'TgGroup',
lazy='joined',
back_populates='chats',
)
messages: Mapped[list['Message']] = relationship(
'Message',
lazy='selectin',
back_populates='chat',
order_by='Message.created_at.desc()',
)
class MessageStatus(enum.Enum):
sending = 'SENDING'
success = 'SUCCESS'
error = 'ERROR'
class Message(BaseModel):
__tablename__ = 'messages'
id: Mapped[int] = mapped_column(primary_key=True)
tg_message_id: Mapped[Optional[int]] = mapped_column(nullable=True)
text: Mapped[str] = mapped_column(nullable=False)
created_at: Mapped[datetime] = mapped_column(nullable=False)
status: Mapped[MessageStatus] = mapped_column(Enum(MessageStatus), nullable=False)
is_deleted: Mapped[bool] = mapped_column(default=False, server_default='0', nullable=False)
tg_sender_id: Mapped[Optional[int]] = mapped_column(
ForeignKey('tg_users.id'),
nullable=True,
)
tg_sender: Mapped[TgUser] = relationship(
'TgUser',
lazy='selectin',
back_populates='messages',
)
crm_sender_id: Mapped[Optional[int]] = mapped_column(
ForeignKey('users.id'),
nullable=True,
)
crm_sender: Mapped[Optional['User']] = relationship(
'User',
lazy='selectin',
back_populates='messages',
)
chat_id: Mapped[int] = mapped_column(ForeignKey('chats.id'))
chat: Mapped[Chat] = relationship(
'Chat',
lazy='noload',
back_populates='messages',
)

View File

@@ -7,7 +7,7 @@ from sqlalchemy.orm import relationship, Mapped, mapped_column
from models import BaseModel
if TYPE_CHECKING:
from models import ResidualPallet, ResidualBox, Product, BarcodeTemplate, User
from models import ResidualPallet, ResidualBox, Product, BarcodeTemplate, User, TgGroup, Chat
class Client(BaseModel):
@@ -39,6 +39,9 @@ class Client(BaseModel):
pallets: Mapped[list['ResidualPallet']] = relationship(back_populates='client', lazy='selectin')
boxes: Mapped[list['ResidualBox']] = relationship(back_populates='client', lazy='selectin')
tg_group: Mapped[Optional['TgGroup']] = relationship('TgGroup', back_populates='client', lazy='joined')
chat: Mapped[Optional['Chat']] = relationship('Chat', back_populates='client', lazy='joined')
class ClientDetails(BaseModel):
__tablename__ = 'client_details'