aee0f09db8
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
277 lines
9.4 KiB
Python
277 lines
9.4 KiB
Python
"""
|
|
quiXzoom Management Module
|
|
Handles missions, contributors, submissions, and payments
|
|
"""
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from datetime import datetime
|
|
|
|
from app.database import get_db
|
|
from app.models import Mission, Contributor, Submission, MissionStatus, User
|
|
from app.core.security import get_current_user
|
|
|
|
router = APIRouter(prefix="/quixzoom", tags=["quixzoom"])
|
|
|
|
# ─── MISSIONS ─────────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/missions")
|
|
async def list_missions(
|
|
status: Optional[MissionStatus] = None,
|
|
city: Optional[str] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""List all missions with optional filtering."""
|
|
query = db.query(Mission)
|
|
if status:
|
|
query = query.filter(Mission.status == status)
|
|
if city:
|
|
query = query.filter(Mission.city.ilike(f"%{city}%"))
|
|
missions = query.offset(skip).limit(limit).all()
|
|
return {
|
|
"missions": [
|
|
{
|
|
"id": m.id,
|
|
"mission_id": m.mission_id,
|
|
"title": m.title,
|
|
"city": m.city,
|
|
"country": m.country,
|
|
"status": m.status.value,
|
|
"reward": f"{m.reward_amount} {m.reward_currency}" if m.reward_amount else None,
|
|
"start_date": m.start_date.isoformat() if m.start_date else None,
|
|
"end_date": m.end_date.isoformat() if m.end_date else None,
|
|
}
|
|
for m in missions
|
|
],
|
|
"total": query.count(),
|
|
}
|
|
|
|
@router.post("/missions")
|
|
async def create_mission(
|
|
mission_id: str,
|
|
title: str,
|
|
city: str,
|
|
country: str,
|
|
reward_amount: float,
|
|
description: Optional[str] = None,
|
|
requirements: Optional[List[str]] = None,
|
|
start_date: Optional[datetime] = None,
|
|
end_date: Optional[datetime] = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Create a new mission."""
|
|
mission = Mission(
|
|
mission_id=mission_id,
|
|
title=title,
|
|
description=description,
|
|
city=city,
|
|
country=country,
|
|
reward_amount=reward_amount,
|
|
requirements=requirements,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
created_by=current_user.id,
|
|
)
|
|
db.add(mission)
|
|
db.commit()
|
|
db.refresh(mission)
|
|
return {"status": "created", "mission_id": mission.id}
|
|
|
|
@router.get("/missions/{mission_id}")
|
|
async def get_mission(
|
|
mission_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Get mission details."""
|
|
mission = db.query(Mission).filter(Mission.id == mission_id).first()
|
|
if not mission:
|
|
raise HTTPException(status_code=404, detail="Mission not found")
|
|
return {
|
|
"id": mission.id,
|
|
"mission_id": mission.mission_id,
|
|
"title": mission.title,
|
|
"description": mission.description,
|
|
"city": mission.city,
|
|
"country": mission.country,
|
|
"location": mission.location,
|
|
"status": mission.status.value,
|
|
"reward_amount": float(mission.reward_amount) if mission.reward_amount else None,
|
|
"reward_currency": mission.reward_currency,
|
|
"requirements": mission.requirements,
|
|
"start_date": mission.start_date.isoformat() if mission.start_date else None,
|
|
"end_date": mission.end_date.isoformat() if mission.end_date else None,
|
|
}
|
|
|
|
@router.put("/missions/{mission_id}")
|
|
async def update_mission(
|
|
mission_id: int,
|
|
title: Optional[str] = None,
|
|
status: Optional[MissionStatus] = None,
|
|
reward_amount: Optional[float] = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Update a mission."""
|
|
mission = db.query(Mission).filter(Mission.id == mission_id).first()
|
|
if not mission:
|
|
raise HTTPException(status_code=404, detail="Mission not found")
|
|
|
|
if title:
|
|
mission.title = title
|
|
if status:
|
|
mission.status = status
|
|
if reward_amount:
|
|
mission.reward_amount = reward_amount
|
|
|
|
db.commit()
|
|
db.refresh(mission)
|
|
return {"status": "updated", "mission_id": mission.id}
|
|
|
|
# ─── CONTRIBUTORS ─────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/contributors")
|
|
async def list_contributors(
|
|
status: Optional[str] = None,
|
|
city: Optional[str] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""List all contributors."""
|
|
query = db.query(Contributor)
|
|
if status:
|
|
query = query.filter(Contributor.status == status)
|
|
if city:
|
|
query = query.filter(Contributor.city.ilike(f"%{city}%"))
|
|
contributors = query.offset(skip).limit(limit).all()
|
|
return {
|
|
"contributors": [
|
|
{
|
|
"id": c.id,
|
|
"contributor_id": c.contributor_id,
|
|
"full_name": c.full_name,
|
|
"email": c.email,
|
|
"city": c.city,
|
|
"country": c.country,
|
|
"reputation_score": c.reputation_score,
|
|
"total_earnings": float(c.total_earnings) if c.total_earnings else 0,
|
|
"total_submissions": c.total_submissions,
|
|
"verified": c.verified,
|
|
"status": c.status,
|
|
}
|
|
for c in contributors
|
|
],
|
|
"total": query.count(),
|
|
}
|
|
|
|
@router.post("/contributors")
|
|
async def create_contributor(
|
|
contributor_id: str,
|
|
full_name: str,
|
|
email: str,
|
|
city: Optional[str] = None,
|
|
country: Optional[str] = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Register a new contributor."""
|
|
contributor = Contributor(
|
|
contributor_id=contributor_id,
|
|
full_name=full_name,
|
|
email=email,
|
|
city=city,
|
|
country=country,
|
|
)
|
|
db.add(contributor)
|
|
db.commit()
|
|
db.refresh(contributor)
|
|
return {"status": "created", "contributor_id": contributor.id}
|
|
|
|
@router.get("/contributors/{contributor_id}")
|
|
async def get_contributor(
|
|
contributor_id: int,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Get contributor details."""
|
|
contributor = db.query(Contributor).filter(Contributor.id == contributor_id).first()
|
|
if not contributor:
|
|
raise HTTPException(status_code=404, detail="Contributor not found")
|
|
return {
|
|
"id": contributor.id,
|
|
"contributor_id": contributor.contributor_id,
|
|
"full_name": contributor.full_name,
|
|
"email": contributor.email,
|
|
"phone": contributor.phone,
|
|
"city": contributor.city,
|
|
"country": contributor.country,
|
|
"reputation_score": contributor.reputation_score,
|
|
"total_earnings": float(contributor.total_earnings) if contributor.total_earnings else 0,
|
|
"total_submissions": contributor.total_submissions,
|
|
"verified": contributor.verified,
|
|
"status": contributor.status,
|
|
}
|
|
|
|
# ─── SUBMISSIONS ──────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/submissions")
|
|
async def list_submissions(
|
|
mission_id: Optional[int] = None,
|
|
status: Optional[str] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""List submissions with filtering."""
|
|
query = db.query(Submission)
|
|
if mission_id:
|
|
query = query.filter(Submission.mission_id == mission_id)
|
|
if status:
|
|
query = query.filter(Submission.status == status)
|
|
submissions = query.offset(skip).limit(limit).all()
|
|
return {
|
|
"submissions": [
|
|
{
|
|
"id": s.id,
|
|
"submission_id": s.submission_id,
|
|
"mission_id": s.mission_id,
|
|
"contributor_id": s.contributor_id,
|
|
"status": s.status,
|
|
"ai_score": s.ai_score,
|
|
"submitted_at": s.submitted_at.isoformat() if s.submitted_at else None,
|
|
"reviewed_at": s.reviewed_at.isoformat() if s.reviewed_at else None,
|
|
}
|
|
for s in submissions
|
|
],
|
|
"total": query.count(),
|
|
}
|
|
|
|
@router.put("/submissions/{submission_id}/review")
|
|
async def review_submission(
|
|
submission_id: int,
|
|
status: str, # approved, rejected
|
|
reviewer_notes: Optional[str] = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Review a submission."""
|
|
submission = db.query(Submission).filter(Submission.id == submission_id).first()
|
|
if not submission:
|
|
raise HTTPException(status_code=404, detail="Submission not found")
|
|
|
|
submission.status = status
|
|
submission.reviewer_notes = reviewer_notes
|
|
submission.reviewed_at = datetime.utcnow()
|
|
submission.reviewed_by = current_user.id
|
|
|
|
db.commit()
|
|
db.refresh(submission)
|
|
return {"status": "reviewed", "submission_id": submission.id, "new_status": status}
|