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

добавление редисаъ5

This commit is contained in:
MoonTestUse1
2025-01-03 16:56:54 +06:00
parent 9f5cb4d4c2
commit 25982e622c
3 changed files with 126 additions and 179 deletions

View File

@@ -1,10 +1,13 @@
"""Initial migration
"""initial migration
Revision ID: initial_migration
Create Date: 2024-03-14 12:00:00.000000
Revises:
Create Date: 2024-01-03 11:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'initial_migration'
@@ -13,7 +16,14 @@ branch_labels = None
depends_on = None
def upgrade() -> None:
# Create employees table
# Создаем enum типы
request_status = postgresql.ENUM('new', 'in_progress', 'completed', 'rejected', name='requeststatus')
request_status.create(op.get_bind())
request_priority = postgresql.ENUM('low', 'medium', 'high', name='requestpriority')
request_priority.create(op.get_bind())
# Создаем таблицу employees
op.create_table(
'employees',
sa.Column('id', sa.Integer(), nullable=False),
@@ -21,29 +31,57 @@ def upgrade() -> None:
sa.Column('last_name', sa.String(), nullable=False),
sa.Column('department', sa.String(), nullable=False),
sa.Column('office', sa.String(), nullable=False),
sa.Column('password', sa.String(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()')),
sa.Column('hashed_password', sa.String(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_employees_id'), 'employees', ['id'], unique=False)
op.create_index(op.f('ix_employees_last_name'), 'employees', ['last_name'], unique=False)
# Create requests table
# Создаем таблицу requests
op.create_table(
'requests',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('title', sa.String(), nullable=False),
sa.Column('description', sa.String(), nullable=False),
sa.Column('status', sa.String(), nullable=False, server_default='new'),
sa.Column('priority', sa.String(), nullable=False),
sa.Column('employee_id', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()')),
sa.Column('updated_at', sa.DateTime(timezone=True), onupdate=sa.text('now()')),
sa.ForeignKeyConstraint(['employee_id'], ['employees.id'], ),
sa.Column('status', sa.Enum('new', 'in_progress', 'completed', 'rejected', name='requeststatus'), nullable=False),
sa.Column('priority', sa.Enum('low', 'medium', 'high', name='requestpriority'), nullable=False),
sa.Column('employee_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['employee_id'], ['employees.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
# Создаем таблицу tokens
op.create_table(
'tokens',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('access_token', sa.String(), nullable=False),
sa.Column('employee_id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['employee_id'], ['employees.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
# Создаем индексы
op.create_index(op.f('ix_employees_id'), 'employees', ['id'], unique=False)
op.create_index(op.f('ix_employees_last_name'), 'employees', ['last_name'], unique=False)
op.create_index(op.f('ix_requests_id'), 'requests', ['id'], unique=False)
op.create_index(op.f('ix_tokens_access_token'), 'tokens', ['access_token'], unique=True)
op.create_index(op.f('ix_tokens_id'), 'tokens', ['id'], unique=False)
def downgrade() -> None:
# Удаляем индексы
op.drop_index(op.f('ix_tokens_id'), table_name='tokens')
op.drop_index(op.f('ix_tokens_access_token'), table_name='tokens')
op.drop_index(op.f('ix_requests_id'), table_name='requests')
op.drop_index(op.f('ix_employees_last_name'), table_name='employees')
op.drop_index(op.f('ix_employees_id'), table_name='employees')
# Удаляем таблицы
op.drop_table('tokens')
op.drop_table('requests')
op.drop_table('employees')
op.drop_table('employees')
# Удаляем enum типы
op.execute('DROP TYPE requeststatus')
op.execute('DROP TYPE requestpriority')

View File

@@ -1,179 +1,78 @@
"""Requests router"""
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Optional
from typing import List
from ..database import get_db
from ..models.request import Request, RequestStatus, RequestPriority
from ..schemas.request import RequestCreate, RequestResponse, RequestUpdate, RequestStatistics
from ..utils.auth import get_current_admin, get_current_employee
from sqlalchemy import func
from ..models.employee import Employee
from ..utils.telegram import notify_new_request, notify_status_change
import logging
# Initialize logger
logger = logging.getLogger(__name__)
from ..crud import requests
from ..schemas.request import Request, RequestCreate, RequestUpdate, RequestStatistics
from ..utils.auth import get_current_employee, get_current_admin
from ..utils.telegram import notify_new_request
router = APIRouter()
def request_to_dict(request: Request) -> dict:
"""Convert Request model to dictionary"""
return {
"id": request.id,
"title": request.title,
"description": request.description,
"priority": request.priority,
"status": request.status,
"employee_id": request.employee_id,
"created_at": request.created_at,
"updated_at": request.updated_at
}
@router.get("/", response_model=List[RequestResponse])
def get_requests(
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""Get all requests"""
try:
requests = db.query(Request).all()
return [request_to_dict(request) for request in requests]
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/", response_model=RequestResponse)
def create_request(
@router.post("", response_model=Request)
async def create_request(
request: RequestCreate,
db: Session = Depends(get_db),
current_employee: dict = Depends(get_current_employee)
):
"""Create new request"""
try:
db_request = Request(
title=request.title,
description=request.description,
priority=request.priority,
status=RequestStatus.NEW,
employee_id=current_employee["id"]
)
db.add(db_request)
db.commit()
db.refresh(db_request)
# Получаем информацию о сотруднике
employee = db.query(Employee).filter(Employee.id == current_employee["id"]).first()
# Преобразуем объект запроса в словарь для уведомления
request_dict = request_to_dict(db_request)
request_dict["employee_name"] = f"{employee.last_name} {employee.first_name}"
# Отправляем уведомление в Telegram
notify_new_request(request_dict)
return request_to_dict(db_request)
except Exception as e:
db.rollback()
logger.error(f"Error creating request: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
"""
Создание новой заявки
"""
db_request = requests.create_request(db=db, request=request, employee_id=current_employee.id)
await notify_new_request(db_request.id)
return db_request
@router.get("/my", response_model=List[RequestResponse])
@router.get("", response_model=List[Request])
def get_employee_requests(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
current_employee: dict = Depends(get_current_employee)
):
"""Get employee's requests"""
try:
requests = db.query(Request).filter(
Request.employee_id == current_employee["id"]
).all()
# Преобразуем объекты в словари до закрытия сессии
return [request_to_dict(request) for request in requests]
except Exception as e:
logger.error(f"Error getting employee requests: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
"""
Получение списка заявок текущего сотрудника
"""
return requests.get_employee_requests(db, employee_id=current_employee.id, skip=skip, limit=limit)
@router.patch("/{request_id}/status", response_model=RequestResponse)
def update_request_status(
request_id: int,
status_update: RequestUpdate,
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""Update request status"""
try:
db_request = db.query(Request).filter(Request.id == request_id).first()
if not db_request:
raise HTTPException(status_code=404, detail="Заявка не найдена")
old_status = db_request.status
db_request.status = status_update.status
db.commit()
db.refresh(db_request)
# Отправляем уведомление об изменении статуса, если у сотрудника есть telegram_id
if db_request.employee and db_request.employee.telegram_id:
notify_status_change(
request_id=db_request.id,
new_status=status_update.status,
employee_telegram_id=db_request.employee.telegram_id
)
return request_to_dict(db_request)
except HTTPException:
raise
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=str(e))
@router.get("/admin", response_model=List[RequestResponse])
def get_all_requests(
status: Optional[str] = None,
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""Get all requests with optional status filter"""
try:
query = db.query(Request)
if status:
query = query.filter(Request.status == status)
requests = query.all()
# Преобразуем объекты в словари до закрытия сессии
return [request_to_dict(request) for request in requests]
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/statistics")
@router.get("/statistics", response_model=RequestStatistics)
def get_request_statistics(
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""Get request statistics"""
try:
total_requests = db.query(Request).count()
# Статистика по статусам
status_stats = db.query(
Request.status,
func.count(Request.id)
).group_by(Request.status).all()
# Статистика по приоритетам
priority_stats = db.query(
Request.priority,
func.count(Request.id)
).group_by(Request.priority).all()
return {
"total_requests": total_requests,
"by_status": {
status: count for status, count in status_stats
},
"by_priority": {
priority: count for priority, count in priority_stats
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
"""
Получение статистики по заявкам (только для админа)
"""
return requests.get_statistics(db)
@router.put("/{request_id}", response_model=Request)
def update_request(
request_id: int,
request_update: RequestUpdate,
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""
Обновление статуса заявки (только для админа)
"""
db_request = requests.get_request(db, request_id=request_id)
if db_request is None:
raise HTTPException(status_code=404, detail="Request not found")
return requests.update_request(db=db, request_id=request_id, request_update=request_update)
@router.delete("/{request_id}")
def delete_request(
request_id: int,
db: Session = Depends(get_db),
_: dict = Depends(get_current_admin)
):
"""
Удаление заявки (только для админа)
"""
db_request = requests.get_request(db, request_id=request_id)
if db_request is None:
raise HTTPException(status_code=404, detail="Request not found")
requests.delete_request(db=db, request_id=request_id)
return {"message": "Request deleted successfully"}

View File

@@ -8,6 +8,7 @@ class RequestStatus(str, Enum):
NEW = "new"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
REJECTED = "rejected"
class RequestPriority(str, Enum):
LOW = "low"
@@ -21,17 +22,26 @@ class RequestBase(BaseModel):
status: RequestStatus = RequestStatus.NEW
class RequestCreate(RequestBase):
employee_id: int
pass
class Request(RequestBase):
class RequestUpdate(BaseModel):
status: RequestStatus
model_config = ConfigDict(from_attributes=True)
class Request(RequestBase):
id: int
employee_id: int
created_at: datetime
updated_at: Optional[datetime] = None
class RequestUpdate(BaseModel):
model_config = ConfigDict(from_attributes=True)
status: RequestStatus
class RequestStatistics(BaseModel):
total: int
new: int
in_progress: int
completed: int
rejected: int
model_config = ConfigDict(from_attributes=True)