1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

Создание чата9testt

This commit is contained in:
MoonTestUse1
2025-01-05 06:32:34 +06:00
parent 9ba671bdaa
commit 7f7838a0d3
28 changed files with 653 additions and 721 deletions

View File

@@ -1,4 +1,4 @@
"""Admin router"""
"""Admin endpoints."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy import func
@@ -19,7 +19,7 @@ def get_statistics(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get system statistics"""
"""Get system statistics."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
@@ -66,7 +66,7 @@ def get_all_requests(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get all requests (admin only)"""
"""Get all requests (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
@@ -83,7 +83,7 @@ def update_request_status(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Update request status (admin only)"""
"""Update request status (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
@@ -106,7 +106,7 @@ def get_all_users(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get all users (admin only)"""
"""Get all users (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,

View File

@@ -1,4 +1,4 @@
"""Authentication router"""
"""Authentication endpoints."""
from datetime import timedelta
from typing import Any
from fastapi import APIRouter, Depends, HTTPException, status
@@ -14,6 +14,7 @@ from app.database import get_db
from app.core.config import settings
from app.models.user import User
from app.schemas.token import Token
from app.schemas.user import User as UserSchema
router = APIRouter()
@@ -22,9 +23,7 @@ def login(
db: Session = Depends(get_db),
form_data: OAuth2PasswordRequestForm = Depends()
) -> Any:
"""
OAuth2 compatible token login, get an access token for future requests
"""
"""OAuth2 compatible token login, get an access token for future requests."""
user = authenticate_user(db, form_data.username, form_data.password)
if not user:
raise HTTPException(
@@ -49,10 +48,8 @@ def login(
"token_type": "bearer"
}
@router.get("/me", response_model=Any)
@router.get("/me", response_model=UserSchema)
def read_users_me(current_user: User = Depends(get_current_user)):
"""
Get current user.
"""
"""Get current user."""
return current_user

View File

@@ -1,137 +1,74 @@
from fastapi import APIRouter, Depends, HTTPException, WebSocket, UploadFile, File
from fastapi import APIRouter, Depends, HTTPException, WebSocket, status
from sqlalchemy.orm import Session
from typing import List
import os
import aiofiles
import uuid
from app.database import get_db
from app.models.user import User
from app.core.auth import get_current_user
from app.schemas.chat import Chat, Message, ChatFile
from app.websockets.chat import handle_chat_connection
from app.core.ws_auth import get_current_user_ws
from app.models.user import User
from app.schemas.chat import (
Chat, ChatCreate,
Message, MessageCreate,
ChatFile, ChatFileCreate
)
router = APIRouter()
# Путь для сохранения файлов
UPLOAD_DIR = "uploads/chat_files"
os.makedirs(UPLOAD_DIR, exist_ok=True)
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, db: Session = Depends(get_db)):
await handle_chat_connection(websocket, db)
@router.post("/files/")
async def upload_file(
file: UploadFile = File(...),
current_user: User = Depends(get_current_user),
async def chat_websocket(
websocket: WebSocket,
db: Session = Depends(get_db)
):
user = await get_current_user_ws(websocket, db)
if not user:
return
await websocket.accept()
try:
# Генерируем уникальное имя файла
file_extension = os.path.splitext(file.filename)[1]
unique_filename = f"{uuid.uuid4()}{file_extension}"
file_path = os.path.join(UPLOAD_DIR, unique_filename)
# Сохраняем файл
async with aiofiles.open(file_path, 'wb') as out_file:
content = await file.read()
await out_file.write(content)
return {
"filename": file.filename,
"saved_path": file_path,
"size": len(content)
}
while True:
data = await websocket.receive_text()
# Обработка сообщений
await websocket.send_text(f"Message received: {data}")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
print(f"Error: {e}")
finally:
await websocket.close()
@router.get("/messages/", response_model=List[Message])
def get_messages(
@router.post("/", response_model=Chat)
def create_chat(
chat: ChatCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
# Получаем чат пользователя
chat = db.query(Chat).filter(
(Chat.employee_id == current_user.id) |
(Chat.admin_id == current_user.id)
).first()
"""Create new chat."""
# Здесь будет логика создания чата
pass
if not chat:
return []
@router.get("/", response_model=List[Chat])
def get_chats(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get all chats for current user."""
# Здесь будет логика получения чатов
pass
# Получаем сообщения
messages = db.query(Message).filter(Message.chat_id == chat.id).all()
return messages
@router.post("/{chat_id}/messages", response_model=Message)
def create_message(
chat_id: int,
message: MessageCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create new message in chat."""
# Здесь будет логика создания сообщения
pass
@router.get("/messages/{chat_id}/", response_model=List[Message])
def get_chat_messages(
@router.get("/{chat_id}/messages", response_model=List[Message])
def get_messages(
chat_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
# Проверяем доступ к чату
chat = db.query(Chat).filter(Chat.id == chat_id).first()
if not chat:
raise HTTPException(status_code=404, detail="Chat not found")
if not current_user.is_admin and chat.employee_id != current_user.id:
raise HTTPException(status_code=403, detail="Not authorized")
# Получаем сообщения
messages = db.query(Message).filter(Message.chat_id == chat_id).all()
return messages
@router.get("/unread-count/")
def get_unread_count(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
# Получаем чат пользователя
chat = db.query(Chat).filter(
(Chat.employee_id == current_user.id) |
(Chat.admin_id == current_user.id)
).first()
if not chat:
return {"unread_count": 0}
# Считаем непрочитанные сообщения
unread_count = db.query(Message).filter(
Message.chat_id == chat.id,
Message.sender_id != current_user.id,
Message.is_read == False
).count()
return {"unread_count": unread_count}
@router.get("/admin/chats/", response_model=List[Chat])
def get_admin_chats(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Not authorized")
# Получаем все чаты с последними сообщениями и количеством непрочитанных
chats = db.query(Chat).all()
# Для каждого чата добавляем дополнительную информацию
for chat in chats:
# Последнее сообщение
last_message = db.query(Message)\
.filter(Message.chat_id == chat.id)\
.order_by(Message.created_at.desc())\
.first()
chat.last_message = last_message
# Количество непрочитанных сообщений
unread_count = db.query(Message)\
.filter(
Message.chat_id == chat.id,
Message.sender_id != current_user.id,
Message.is_read == False
).count()
chat.unread_count = unread_count
return chats
"""Get all messages in chat."""
# Здесь будет логика получения сообщений
pass

View File

@@ -1,52 +1,86 @@
"""Employee router"""
"""Employee endpoints."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List
from app.core.auth import get_current_user, get_password_hash
from app.database import get_db
from app.models.user import User
from app.schemas.user import UserCreate, User as UserSchema
from app.core.auth import get_current_user, get_password_hash
from app.schemas.user import User as UserSchema, UserCreate, UserUpdate
router = APIRouter()
@router.post("/", response_model=UserSchema)
def create_employee(
user: UserCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
# Проверяем, не существует ли уже пользователь с таким email
"""Create new employee (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
# Проверяем, не существует ли пользователь с таким email
db_user = db.query(User).filter(User.email == user.email).first()
if db_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
# Создаем нового пользователя
# Создаем пользователя
hashed_password = get_password_hash(user.password)
db_user = User(
email=user.email,
full_name=user.full_name,
hashed_password=hashed_password,
is_admin=False
is_admin=user.is_admin
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
@router.get("/", response_model=List[UserSchema])
def read_employees(
skip: int = 0,
limit: int = 100,
@router.get("/me", response_model=UserSchema)
def get_current_employee(current_user: User = Depends(get_current_user)):
"""Get current employee info."""
return current_user
@router.put("/me", response_model=UserSchema)
def update_employee_me(
user_update: UserUpdate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Update current employee info."""
update_data = user_update.model_dump(exclude_unset=True)
if "password" in update_data:
update_data["hashed_password"] = get_password_hash(update_data.pop("password"))
for key, value in update_data.items():
setattr(current_user, key, value)
db.commit()
db.refresh(current_user)
return current_user
@router.get("/{employee_id}", response_model=UserSchema)
def get_employee(
employee_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get employee by ID (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
users = db.query(User).filter(User.is_admin == False).offset(skip).limit(limit).all()
return users
employee = db.query(User).filter(User.id == employee_id).first()
if not employee:
raise HTTPException(status_code=404, detail="Employee not found")
return employee

View File

@@ -1,13 +1,12 @@
"""Requests router"""
from fastapi import APIRouter, Depends, HTTPException, status
"""Request endpoints."""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from app.core.auth import get_current_user
from app.database import get_db
from app.models.user import User
from app.models.request import Request
from app.schemas.request import RequestCreate, Request as RequestSchema
from app.core.auth import get_current_user
router = APIRouter()
@@ -17,89 +16,34 @@ def create_request(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create new request"""
"""Create new request."""
db_request = Request(
**request.dict(),
employee_id=current_user.id,
status="new"
**request.model_dump()
)
db.add(db_request)
db.commit()
db.refresh(db_request)
return db_request
@router.get("/", response_model=List[RequestSchema])
def read_requests(
skip: int = 0,
limit: int = 100,
@router.get("/my", response_model=List[RequestSchema])
def get_my_requests(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get all requests (admin only)"""
if current_user.is_admin:
requests = db.query(Request).offset(skip).limit(limit).all()
else:
requests = db.query(Request).filter(
Request.employee_id == current_user.id
).offset(skip).limit(limit).all()
return requests
"""Get current user's requests."""
return db.query(Request).filter(Request.employee_id == current_user.id).all()
@router.get("/{request_id}", response_model=RequestSchema)
def read_request(
def get_request(
request_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get a specific request"""
"""Get request by ID."""
request = db.query(Request).filter(Request.id == request_id).first()
if not request:
raise HTTPException(status_code=404, detail="Request not found")
# Проверяем права доступа
if not current_user.is_admin and request.employee_id != current_user.id:
raise HTTPException(status_code=403, detail="Not enough permissions")
return request
@router.put("/{request_id}", response_model=RequestSchema)
def update_request(
request_id: int,
request_update: RequestCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Update a request"""
db_request = db.query(Request).filter(Request.id == request_id).first()
if not db_request:
raise HTTPException(status_code=404, detail="Request not found")
# Проверяем права доступа
if not current_user.is_admin and db_request.employee_id != current_user.id:
raise HTTPException(status_code=403, detail="Not enough permissions")
# Обновляем заявку
for key, value in request_update.dict().items():
setattr(db_request, key, value)
db.commit()
db.refresh(db_request)
return db_request
@router.delete("/{request_id}", response_model=RequestSchema)
def delete_request(
request_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Delete a request"""
db_request = db.query(Request).filter(Request.id == request_id).first()
if not db_request:
raise HTTPException(status_code=404, detail="Request not found")
# Только админ может удалять заявки
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Not enough permissions")
db.delete(db_request)
db.commit()
return db_request
raise HTTPException(status_code=403, detail="Not authorized to access this request")
return request

View File

@@ -1,13 +1,13 @@
"""Statistics router"""
"""Statistics endpoints."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy import func
from datetime import datetime, timedelta
from app.core.auth import get_current_user
from app.database import get_db
from app.models.user import User
from app.models.request import Request
from app.core.auth import get_current_user
router = APIRouter()
@@ -16,6 +16,7 @@ def get_statistics(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get system statistics (admin only)."""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,

View File

@@ -62,31 +62,4 @@ async def get_current_user(
user = db.query(User).filter(User.email == email).first()
if user is None:
raise credentials_exception
return user
async def get_current_user_ws(websocket: WebSocket, db: Session = Depends(get_db)) -> Optional[User]:
try:
# Получаем токен из параметров запроса
token = websocket.query_params.get("token")
if not token:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
# Проверяем токен
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
# Получаем пользователя
user = db.query(User).filter(User.email == email).first()
if user is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
return user
except JWTError:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
return user

View File

@@ -5,15 +5,29 @@ from typing import Optional
class Settings(BaseSettings):
"""Application settings"""
PROJECT_NAME: str = "Support System"
VERSION: str = "1.0.0"
API_V1_STR: str = "/api"
SECRET_KEY: str = "your-secret-key-for-jwt" # В продакшене использовать безопасный ключ
# Security
SECRET_KEY: str = "your-secret-key-for-jwt"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 # 8 дней
# Database
POSTGRES_SERVER: str = "db"
POSTGRES_USER: str = "postgres"
POSTGRES_PASSWORD: str = "postgres"
POSTGRES_DB: str = "support_db"
SQLALCHEMY_DATABASE_URI: Optional[str] = None
DATABASE_URL: Optional[str] = None
# Redis
REDIS_HOST: str = "redis"
REDIS_PORT: int = 6379
REDIS_DB: int = 0
REDIS_PASSWORD: Optional[str] = None
# Telegram
TELEGRAM_BOT_TOKEN: Optional[str] = None
TELEGRAM_CHAT_ID: Optional[str] = None
@property
def get_database_url(self) -> str:
@@ -23,6 +37,8 @@ class Settings(BaseSettings):
class Config:
case_sensitive = True
env_file = ".env"
extra = "allow" # Разрешаем дополнительные поля
settings = Settings()
settings.SQLALCHEMY_DATABASE_URI = settings.get_database_url
if not settings.DATABASE_URL:
settings.DATABASE_URL = settings.get_database_url

10
backend/app/core/redis.py Normal file
View File

@@ -0,0 +1,10 @@
import redis
from app.core.config import settings
redis_client = redis.Redis(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DB,
password=settings.REDIS_PASSWORD,
decode_responses=True
)

View File

@@ -0,0 +1,34 @@
from typing import Optional
from fastapi import WebSocket, status
from jose import JWTError, jwt
from sqlalchemy.orm import Session
from app.core.config import settings
from app.models.user import User
async def get_current_user_ws(websocket: WebSocket, db: Session) -> Optional[User]:
"""Get current user from WebSocket connection."""
try:
# Получаем токен из параметров запроса
token = websocket.query_params.get("token")
if not token:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
# Проверяем токен
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
email: str = payload.get("sub")
if email is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
# Получаем пользователя
user = db.query(User).filter(User.email == email).first()
if user is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None
return user
except JWTError:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return None

View File

@@ -1,20 +1,21 @@
"""Database configuration"""
"""Database configuration."""
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from .core.config import settings
from .db.base import Base
from app.core.config import settings
# Для создания таблиц импортируем модели
from .models.employee import Employee # noqa
from .models.request import Request # noqa
from .models.token import Token # noqa
SQLALCHEMY_DATABASE_URL = settings.DATABASE_URL
engine = create_engine(SQLALCHEMY_DATABASE_URL)
engine = create_engine(settings.DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# Import all models here
from app.models.user import User # noqa
from app.models.request import Request # noqa
from app.models.chat import Chat, Message, ChatFile # noqa
def get_db():
"""Get database session."""
db = SessionLocal()
try:
yield db

View File

@@ -1,4 +1,4 @@
"""Main application module"""
"""Main application module."""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
@@ -6,6 +6,7 @@ from app.api.endpoints import admin, employees, requests, auth, statistics, chat
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
openapi_url=f"{settings.API_V1_STR}/openapi.json"
)
@@ -28,4 +29,9 @@ app.include_router(chat.router, prefix=f"{settings.API_V1_STR}/chat", tags=["cha
@app.get("/")
def read_root():
return {"message": "Welcome to Support System API"}
"""Root endpoint."""
return {
"message": "Welcome to Support System API",
"version": settings.VERSION,
"docs_url": "/docs"
}

View File

@@ -1,45 +1,46 @@
"""Chat models."""
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Text
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from app.database import Base
class Chat(Base):
"""Chat model."""
__tablename__ = "chats"
id = Column(Integer, primary_key=True, index=True)
employee_id = Column(Integer, ForeignKey("users.id"), nullable=False, unique=True)
admin_id = Column(Integer, ForeignKey("users.id"), nullable=False)
employee_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
# Отношения
employee = relationship("User", foreign_keys=[employee_id], back_populates="employee_chats")
admin = relationship("User", foreign_keys=[admin_id], back_populates="admin_chats")
employee = relationship("User", back_populates="chats")
messages = relationship("Message", back_populates="chat", cascade="all, delete-orphan")
class Message(Base):
"""Message model."""
__tablename__ = "messages"
id = Column(Integer, primary_key=True, index=True)
chat_id = Column(Integer, ForeignKey("chats.id", ondelete="CASCADE"), nullable=False)
sender_id = Column(Integer, ForeignKey("users.id"), nullable=False)
sender_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
content = Column(Text, nullable=False)
is_read = Column(Boolean, default=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
# Отношения
chat = relationship("Chat", back_populates="messages")
sender = relationship("User", back_populates="sent_messages")
sender = relationship("User", back_populates="messages")
files = relationship("ChatFile", back_populates="message", cascade="all, delete-orphan")
class ChatFile(Base):
"""Chat file model."""
__tablename__ = "chat_files"
id = Column(Integer, primary_key=True, index=True)
message_id = Column(Integer, ForeignKey("messages.id", ondelete="CASCADE"), nullable=False)
file_name = Column(String(255), nullable=False)
file_path = Column(String(255), nullable=False)
file_size = Column(Integer, nullable=False)
filename = Column(String, nullable=False)
file_path = Column(String, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
# Отношения

View File

@@ -1,18 +1,20 @@
"""Request model"""
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Text
"""Request model."""
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Text, Enum
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from app.db.base_class import Base
from app.database import Base
from app.schemas.request import RequestPriority, RequestStatus
class Request(Base):
"""Request model."""
__tablename__ = "requests"
id = Column(Integer, primary_key=True, index=True)
employee_id = Column(Integer, ForeignKey("users.id"), nullable=False)
employee_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
request_type = Column(String, nullable=False)
description = Column(Text, nullable=False)
priority = Column(String, nullable=False)
status = Column(String, default="new")
priority = Column(Enum(RequestPriority), nullable=False)
status = Column(Enum(RequestStatus), default=RequestStatus.NEW)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())

View File

@@ -1,9 +1,10 @@
"""User model."""
from sqlalchemy import Boolean, Column, Integer, String
from sqlalchemy.orm import relationship
from app.database import Base
class User(Base):
"""User model."""
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
@@ -13,10 +14,7 @@ class User(Base):
is_active = Column(Boolean, default=True)
is_admin = Column(Boolean, default=False)
# Отношения для чата
employee_chats = relationship("Chat", foreign_keys="[Chat.employee_id]", back_populates="employee")
admin_chats = relationship("Chat", foreign_keys="[Chat.admin_id]", back_populates="admin")
sent_messages = relationship("Message", back_populates="sender")
# Отношения для заявок
requests = relationship("Request", back_populates="employee")
# Отношения
requests = relationship("Request", back_populates="employee")
chats = relationship("Chat", back_populates="employee")
messages = relationship("Message", back_populates="sender")

View File

@@ -1,74 +1,54 @@
"""Chat schemas"""
"""Chat schemas."""
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional, List
from app.models.user import User
class ChatBase(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
employee_id: int
class ChatCreate(ChatBase):
pass
class MessageBase(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
content: str
chat_id: int
sender_id: int
class MessageCreate(MessageBase):
pass
class ChatFileBase(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
"""Chat file base schema."""
model_config = ConfigDict(from_attributes=True)
filename: str
file_path: str
message_id: int
class ChatFileCreate(ChatFileBase):
pass
"""Chat file create schema."""
message_id: int
class ChatFile(ChatFileBase):
"""Chat file schema."""
id: int
message_id: int
created_at: datetime
class Config:
from_attributes = True
class MessageBase(BaseModel):
"""Message base schema."""
model_config = ConfigDict(from_attributes=True)
content: str
class MessageCreate(MessageBase):
"""Message create schema."""
chat_id: int
class Message(MessageBase):
"""Message schema."""
id: int
chat_id: int
sender_id: int
is_read: bool
created_at: datetime
files: List[ChatFile] = []
class Config:
from_attributes = True
class ChatBase(BaseModel):
"""Chat base schema."""
model_config = ConfigDict(from_attributes=True)
employee_id: int
class ChatCreate(ChatBase):
"""Chat create schema."""
pass
class Chat(ChatBase):
"""Chat schema."""
id: int
employee: User
messages: List[Message] = []
created_at: datetime
updated_at: Optional[datetime] = None
class Config:
from_attributes = True
# Схемы для WebSocket сообщений
class WSMessage(BaseModel):
type: str
content: Optional[str] = None
message_ids: Optional[List[int]] = None
files: Optional[List[dict]] = None
class WSResponse(BaseModel):
type: str
id: Optional[int] = None
sender_id: Optional[int] = None
content: Optional[str] = None
created_at: Optional[datetime] = None
is_read: Optional[bool] = None
message_ids: Optional[List[int]] = None
files: Optional[List[ChatFile]] = None
error: Optional[str] = None
messages: List[Message] = []

View File

@@ -1,27 +1,42 @@
"""Request schemas"""
"""Request schemas."""
from pydantic import BaseModel, ConfigDict
from datetime import datetime
from typing import Optional
from enum import Enum
class RequestPriority(str, Enum):
"""Request priority enum."""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class RequestStatus(str, Enum):
"""Request status enum."""
NEW = "new"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
REJECTED = "rejected"
class RequestBase(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
"""Request base schema."""
model_config = ConfigDict(from_attributes=True)
request_type: str
description: str
priority: str
priority: RequestPriority
class RequestCreate(RequestBase):
"""Request create schema."""
pass
class RequestUpdate(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
status: str
"""Request update schema."""
model_config = ConfigDict(from_attributes=True)
status: RequestStatus
class Request(RequestBase):
"""Request schema."""
id: int
employee_id: int
status: str
status: RequestStatus
created_at: datetime
updated_at: Optional[datetime] = None
class Config:
from_attributes = True
updated_at: Optional[datetime] = None

View File

@@ -1,13 +1,7 @@
"""Token schemas"""
from pydantic import BaseModel, ConfigDict
"""Token schemas."""
from pydantic import BaseModel
class Token(BaseModel):
"""Token schema."""
access_token: str
token_type: str
model_config = ConfigDict(from_attributes=True)
class TokenData(BaseModel):
user_id: int | None = None
model_config = ConfigDict(from_attributes=True)
token_type: str

View File

@@ -1,19 +1,26 @@
"""User schemas"""
"""User schemas."""
from pydantic import BaseModel, EmailStr, ConfigDict
from typing import Optional
class UserBase(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
"""User base schema."""
model_config = ConfigDict(from_attributes=True)
email: EmailStr
full_name: str
is_admin: bool = False
class UserCreate(UserBase):
"""User create schema."""
password: str
class User(UserBase):
id: int
is_active: bool = True
class UserUpdate(BaseModel):
"""User update schema."""
model_config = ConfigDict(from_attributes=True)
email: Optional[EmailStr] = None
full_name: Optional[str] = None
password: Optional[str] = None
class Config:
from_attributes = True
class User(UserBase):
"""User schema."""
id: int
is_active: bool = True