landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
"""
|
||||
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}
|
||||
Reference in New Issue
Block a user