packlist/backend/routes/items.py

122 lines
3.5 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session, joinedload
from uuid import UUID
from database import get_db
import models
from schemas import ItemCreate, ItemOut, TagIdPayload, TagOut
from crud import generate_trip_items
router = APIRouter(prefix="/items", tags=["items"])
@router.get("/", response_model=list[ItemOut])
def list_items(db: Session = Depends(get_db)):
items = db.query(models.Item).options(joinedload(models.Item.tags)).all()
return items
def regenerate_all_trips(db):
trips = db.query(models.Trip).all()
for trip in trips:
generate_trip_items(
db,
trip=trip,
selected_tag_ids=[t.id for t in trip.selected_tags],
marked_tag_ids=[t.id for t in trip.marked_tags],
)
db.commit()
@router.post("/", response_model=ItemOut)
def create_item(payload: ItemCreate, db: Session = Depends(get_db)):
user = db.query(models.User).first()
if not user:
from uuid import uuid4
user = models.User(id=uuid4(), name="Demo")
db.add(user)
db.flush()
item = models.Item(user_id=user.id, name=payload.name, trip_id=payload.trip_id)
# Attach tags if provided
if payload.tag_ids:
tags = (
db.query(models.Tag)
.filter(models.Tag.id.in_(payload.tag_ids), models.Tag.user_id == user.id)
.all()
)
item.tags.extend(tags)
db.add(item)
db.commit()
db.refresh(item)
regenerate_all_trips(db)
return item
@router.post("/{item_id}/tags", response_model=ItemOut)
def add_tag_to_item(item_id: UUID, payload: TagIdPayload, db: Session = Depends(get_db)):
tag_id = payload.tag_id
item = db.get(models.Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
tag = db.get(models.Tag, tag_id)
if not tag or tag.user_id != item.user_id:
raise HTTPException(status_code=404, detail="Tag not found")
if tag in item.tags:
raise HTTPException(status_code=400, detail="Tag already associated with item")
item.tags.append(tag)
db.commit()
db.refresh(item)
regenerate_all_trips(db)
return item
@router.delete("/{item_id}/tags/{tag_id}", response_model=ItemOut)
def remove_tag_from_item(item_id: UUID, tag_id: UUID, db: Session = Depends(get_db)):
item = db.get(models.Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
tag = db.get(models.Tag, tag_id)
if not tag or tag.user_id != item.user_id:
raise HTTPException(status_code=404, detail="Tag not found")
item.tags.remove(tag)
db.commit()
db.refresh(item)
regenerate_all_trips(db)
return item
@router.delete("/{item_id}", status_code=204)
def delete_item(item_id: UUID, db: Session = Depends(get_db)):
item = db.get(models.Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
db.delete(item)
db.commit()
regenerate_all_trips(db)
@router.put("/{item_id}", response_model=ItemOut)
def update_item_name(item_id: UUID, payload: dict, db: Session = Depends(get_db)):
item = db.get(models.Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
name = payload.get("name")
if not name or not isinstance(name, str):
raise HTTPException(status_code=400, detail="Missing or invalid name")
item.name = name
db.commit()
db.refresh(item)
regenerate_all_trips(db)
return item