133 lines
5.0 KiB
Python
133 lines
5.0 KiB
Python
import os
|
|
from typing import Optional, List
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.application.solution_files_repository import SolutionFilesRepository
|
|
from app.application.solutions_repository import SolutionsRepository
|
|
from app.application.tasks_repository import TasksRepository
|
|
from app.application.users_repository import UsersRepository
|
|
from app.domain.entities.solutions import SolutionRead, SolutionCreate, SolutionAfterCreate, AssessmentCreate
|
|
from app.domain.models import User, Solution
|
|
from app.settings import Settings
|
|
|
|
|
|
class SolutionsService:
|
|
def __init__(self, db: AsyncSession):
|
|
self.solutions_repository = SolutionsRepository(db)
|
|
self.tasks_repository = TasksRepository(db)
|
|
self.users_repository = UsersRepository(db)
|
|
self.solution_files_repository = SolutionFilesRepository(db)
|
|
self.settings = Settings()
|
|
|
|
async def get_by_task_id(self, task_id: int) -> Optional[List[SolutionRead]]:
|
|
task_model = await self.tasks_repository.get_by_id(task_id)
|
|
|
|
if task_model is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Задание не найдено"
|
|
)
|
|
|
|
solutions = await self.solutions_repository.get_by_task_id(task_id)
|
|
|
|
response = []
|
|
for solution in solutions:
|
|
response.append(
|
|
SolutionRead.model_validate(solution)
|
|
)
|
|
|
|
return response
|
|
|
|
async def get_by_task_id_and_student_id(self, task_id: int, student_id: int) -> Optional[List[SolutionRead]]:
|
|
task_model = await self.tasks_repository.get_by_id(task_id)
|
|
|
|
if task_model is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Задание не найдено"
|
|
)
|
|
|
|
student_model = await self.users_repository.get_by_id(student_id)
|
|
|
|
if student_model is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Такой пользователь не найден"
|
|
)
|
|
|
|
solutions = await self.solutions_repository.get_by_task_id_and_student_id(task_id, student_id)
|
|
|
|
response = []
|
|
for solution in solutions:
|
|
response.append(
|
|
SolutionRead.model_validate(solution)
|
|
)
|
|
|
|
return response
|
|
|
|
async def create_assessment(self, solution_id: int, assessment: AssessmentCreate, user: User) -> None:
|
|
solution_model = await self.solutions_repository.get_by_id(solution_id)
|
|
|
|
if solution_model is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Такого решения не найдено"
|
|
)
|
|
|
|
solution_model.assessment = assessment.assessment
|
|
solution_model.assessment_autor_id = user.id
|
|
|
|
await self.solutions_repository.update(solution_model)
|
|
|
|
async def create(self, solution: SolutionCreate, creator: User, task_id: int) -> SolutionAfterCreate:
|
|
task_model = await self.tasks_repository.get_by_id(task_id)
|
|
|
|
if task_model is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Задание не найдено"
|
|
)
|
|
|
|
model_solution = Solution(
|
|
answer_text=solution.answer_text,
|
|
assessment=solution.assessment,
|
|
task_id=task_id,
|
|
student_id=creator.id,
|
|
)
|
|
created_solution = await self.solutions_repository.create(model_solution)
|
|
return SolutionAfterCreate.model_validate(created_solution)
|
|
|
|
async def delete(self, solution_id: int, current_user: User) -> Optional[SolutionRead]:
|
|
solution = await self.solutions_repository.get_by_id(solution_id)
|
|
if solution is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail='Такое решение не найдено'
|
|
)
|
|
|
|
is_admin = current_user.role.title == self.settings.root_role_name
|
|
if solution.student_id != current_user.id and not is_admin:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Доступ запрещён"
|
|
)
|
|
|
|
solution_files = await self.solution_files_repository.get_by_solution_id(solution.id)
|
|
for file in solution_files:
|
|
solution_file = await self.solution_files_repository.get_by_id(file.id)
|
|
|
|
if solution_file is None:
|
|
raise HTTPException(404, "Файл не найден")
|
|
|
|
if not os.path.exists(solution_file.file_path):
|
|
raise HTTPException(404, "Файл не найден на диске")
|
|
|
|
if os.path.exists(solution_file.file_path):
|
|
os.remove(solution_file.file_path)
|
|
|
|
await self.solution_files_repository.delete(solution_file)
|
|
|
|
await self.solutions_repository.delete(solution)
|