it-planet-springboard/api/app/infrastructure/internships_service.py

95 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import datetime
from typing import List, Optional
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import HTTPException, status
from app.domain.entities.internships import InternshipCreate, InternshipUpdate
from app.domain.models import Internship, User
class InternshipsService:
def __init__(self, db: AsyncSession):
self.db = db
async def create_internship(self, data: InternshipCreate, user: User) -> Internship:
"""
Создает новую стажировку, автоматически привязывая её к компании юзера.
"""
# 1. Проверяем, что у пользователя заполнена компания
if not user.company_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Пользователь не привязан к профилю компании"
)
# 2. Превращаем Pydantic модель в словарь
internship_data = data.model_dump()
# 3. Автозаполнение технических полей, которые фронт не должен присылать
internship_data['company_id'] = user.company_id
internship_data['published_at'] = datetime.now()
# Устанавливаем статус модерации "Новая" (обычно ID=1)
if internship_data.get('moderation_status_id') is None:
internship_data['moderation_status_id'] = 1
# Заглушка для location_id, если логика локаций еще не реализована полностью
if internship_data.get('location_id') is None:
internship_data['location_id'] = 1
# 4. Создаем объект модели SQLAlchemy
new_internship = Internship(**internship_data)
# 5. Сохраняем в базу
self.db.add(new_internship)
try:
await self.db.commit()
await self.db.refresh(new_internship)
except Exception as e:
await self.db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Ошибка при сохранении в базу данных: {str(e)}"
)
# Подгружаем связанные данные для InternshipRead (если нужно в ответе)
# Это предотвратит ошибки Lazy Loading при возврате InternshipRead
query = select(Internship).where(Internship.id == new_internship.id)
# Если в моделях прописаны отношения, можно добавить .options(selectinload(...))
return new_internship
async def get_internships(self, limit: int = 10, offset: int = 0) -> List[Internship]:
"""Получение списка всех активных стажировок."""
query = select(Internship).where(Internship.is_active == True).limit(limit).offset(offset)
result = await self.db.execute(query)
return result.scalars().all()
async def get_internship_by_id(self, internship_id: int) -> Optional[Internship]:
"""Получение конкретной стажировки по ID."""
query = select(Internship).where(Internship.id == internship_id)
result = await self.db.execute(query)
internship = result.scalar_one_or_none()
if not internship:
raise HTTPException(status_code=404, detail="Стажировка не найдена")
return internship
async def update_internship(self, internship_id: int, data: InternshipUpdate, user: User) -> Internship:
"""Обновление данных стажировки (только для владельца компании)."""
internship = await self.get_internship_by_id(internship_id)
if internship.company_id != user.company_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Вы не можете редактировать чужую стажировку"
)
update_data = data.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(internship, key, value)
await self.db.commit()
await self.db.refresh(internship)
return internship