alabuga/backend/app/api/routes/admin.py
danilgryaznev e050bd46ef 1 vers
2025-09-21 19:30:55 +02:00

168 lines
5.8 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.

"""HR-панель и административные действия."""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app.api.deps import require_hr
from app.db.session import get_db
from app.models.branch import BranchMission
from app.models.mission import Mission, MissionCompetencyReward, MissionPrerequisite, MissionSubmission, SubmissionStatus
from app.models.rank import Rank
from app.schemas.mission import MissionBase, MissionCreate, MissionDetail, MissionSubmissionRead
from app.schemas.rank import RankBase
from app.services.mission import approve_submission, reject_submission
router = APIRouter(prefix="/api/admin", tags=["admin"])
@router.get("/missions", response_model=list[MissionBase], summary="Миссии (HR)")
def admin_missions(*, db: Session = Depends(get_db), current_user=Depends(require_hr)) -> list[MissionBase]:
"""Список всех миссий для HR."""
missions = db.query(Mission).order_by(Mission.title).all()
return [MissionBase.model_validate(mission) for mission in missions]
@router.post("/missions", response_model=MissionDetail, summary="Создать миссию")
def create_mission_endpoint(
mission_in: MissionCreate,
*,
db: Session = Depends(get_db),
current_user=Depends(require_hr),
) -> MissionDetail:
"""Создаём новую миссию."""
mission = Mission(
title=mission_in.title,
description=mission_in.description,
xp_reward=mission_in.xp_reward,
mana_reward=mission_in.mana_reward,
difficulty=mission_in.difficulty,
minimum_rank_id=mission_in.minimum_rank_id,
artifact_id=mission_in.artifact_id,
)
db.add(mission)
db.flush()
for reward in mission_in.competency_rewards:
db.add(
MissionCompetencyReward(
mission_id=mission.id,
competency_id=reward.competency_id,
level_delta=reward.level_delta,
)
)
for prerequisite_id in mission_in.prerequisite_ids:
db.add(
MissionPrerequisite(mission_id=mission.id, required_mission_id=prerequisite_id)
)
if mission_in.branch_id:
db.add(
BranchMission(
branch_id=mission_in.branch_id,
mission_id=mission.id,
order=mission_in.branch_order,
)
)
db.commit()
db.refresh(mission)
return MissionDetail(
id=mission.id,
title=mission.title,
description=mission.description,
xp_reward=mission.xp_reward,
mana_reward=mission.mana_reward,
difficulty=mission.difficulty,
is_active=mission.is_active,
minimum_rank_id=mission.minimum_rank_id,
artifact_id=mission.artifact_id,
prerequisites=[link.required_mission_id for link in mission.prerequisites],
competency_rewards=[
{
"competency_id": reward.competency_id,
"competency_name": reward.competency.name,
"level_delta": reward.level_delta,
}
for reward in mission.competency_rewards
],
created_at=mission.created_at,
updated_at=mission.updated_at,
)
@router.get("/ranks", response_model=list[RankBase], summary="Список рангов")
def admin_ranks(*, db: Session = Depends(get_db), current_user=Depends(require_hr)) -> list[RankBase]:
"""Перечень рангов."""
ranks = db.query(Rank).order_by(Rank.required_xp).all()
return [RankBase.model_validate(rank) for rank in ranks]
@router.get(
"/submissions",
response_model=list[MissionSubmissionRead],
summary="Очередь модерации",
)
def moderation_queue(
status_filter: SubmissionStatus = SubmissionStatus.PENDING,
*,
db: Session = Depends(get_db),
current_user=Depends(require_hr),
) -> list[MissionSubmissionRead]:
"""Возвращаем отправки со статусом по умолчанию pending."""
submissions = (
db.query(MissionSubmission)
.filter(MissionSubmission.status == status_filter)
.order_by(MissionSubmission.created_at)
.all()
)
return [MissionSubmissionRead.model_validate(submission) for submission in submissions]
@router.post(
"/submissions/{submission_id}/approve",
response_model=MissionSubmissionRead,
summary="Одобрить миссию",
)
def approve_submission_endpoint(
submission_id: int,
*,
db: Session = Depends(get_db),
current_user=Depends(require_hr),
) -> MissionSubmissionRead:
"""HR подтверждает выполнение."""
submission = db.query(MissionSubmission).filter(MissionSubmission.id == submission_id).first()
if not submission:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Отправка не найдена")
submission = approve_submission(db, submission)
return MissionSubmissionRead.model_validate(submission)
@router.post(
"/submissions/{submission_id}/reject",
response_model=MissionSubmissionRead,
summary="Отклонить миссию",
)
def reject_submission_endpoint(
submission_id: int,
comment: str | None = None,
*,
db: Session = Depends(get_db),
current_user=Depends(require_hr),
) -> MissionSubmissionRead:
"""HR отклоняет выполнение."""
submission = db.query(MissionSubmission).filter(MissionSubmission.id == submission_id).first()
if not submission:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Отправка не найдена")
submission = reject_submission(db, submission, comment)
return MissionSubmissionRead.model_validate(submission)