tickethub/backend/app/routers/projects.py

114 lines
3.7 KiB
Python

from fastapi import APIRouter, HTTPException
from typing import List
from app.models import Project, ProjectCreate
from app.services.database import get_db
import json
router = APIRouter()
@router.get("", response_model=List[Project])
async def list_projects():
db = await get_db()
cursor = await db.execute("""
SELECT p.*, COUNT(t.id) as ticket_count
FROM projects p
LEFT JOIN tickets t ON p.id = t.project_id
GROUP BY p.id
""")
rows = await cursor.fetchall()
await db.close()
return [dict(row) for row in rows]
@router.post("", response_model=Project)
async def create_project(project: ProjectCreate):
db = await get_db()
try:
cursor = await db.execute(
"INSERT INTO projects (name, key, description, webhook_url) VALUES (?, ?, ?, ?)",
(project.name, project.key.upper(), project.description, project.webhook_url)
)
await db.commit()
project_id = cursor.lastrowid
cursor = await db.execute("SELECT * FROM projects WHERE id = ?", (project_id,))
row = await cursor.fetchone()
await db.close()
return {**dict(row), "ticket_count": 0}
except Exception as e:
await db.close()
raise HTTPException(status_code=400, detail=str(e))
@router.get("/{project_id}", response_model=Project)
async def get_project(project_id: int):
db = await get_db()
cursor = await db.execute("""
SELECT p.*, COUNT(t.id) as ticket_count
FROM projects p
LEFT JOIN tickets t ON p.id = t.project_id
WHERE p.id = ?
GROUP BY p.id
""", (project_id,))
row = await cursor.fetchone()
await db.close()
if not row:
raise HTTPException(status_code=404, detail="Project not found")
return dict(row)
@router.delete("/{project_id}")
async def delete_project(project_id: int):
db = await get_db()
await db.execute("DELETE FROM tickets WHERE project_id = ?", (project_id,))
await db.execute("DELETE FROM webhooks WHERE project_id = ?", (project_id,))
await db.execute("DELETE FROM projects WHERE id = ?", (project_id,))
await db.commit()
await db.close()
return {"status": "deleted"}
from pydantic import BaseModel
from typing import Optional
class ProjectUpdate(BaseModel):
name: Optional[str] = None
description: Optional[str] = None
webhook_url: Optional[str] = None
@router.patch("/{project_id}", response_model=Project)
async def update_project(project_id: int, update: ProjectUpdate):
db = await get_db()
# Check if exists
cursor = await db.execute("SELECT * FROM projects WHERE id = ?", (project_id,))
if not await cursor.fetchone():
await db.close()
raise HTTPException(status_code=404, detail="Project not found")
# Build update query
updates = []
params = []
if update.name is not None:
updates.append("name = ?")
params.append(update.name)
if update.description is not None:
updates.append("description = ?")
params.append(update.description if update.description else None)
if update.webhook_url is not None:
updates.append("webhook_url = ?")
params.append(update.webhook_url if update.webhook_url else None)
if updates:
params.append(project_id)
await db.execute(f"UPDATE projects SET {', '.join(updates)} WHERE id = ?", params)
await db.commit()
cursor = await db.execute("""
SELECT p.*, COUNT(t.id) as ticket_count
FROM projects p
LEFT JOIN tickets t ON p.id = t.project_id
WHERE p.id = ?
GROUP BY p.id
""", (project_id,))
row = await cursor.fetchone()
await db.close()
return dict(row)