summaryrefslogtreecommitdiff
path: root/routers/pantry.py
blob: d6638f89a39402738d14211c7147e57b916f4097 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from datetime import datetime, timedelta
from typing import List

from database import get_db
from models import Ingredient
from schemas import IngredientCreate, IngredientRead, IngredientUpdate

router = APIRouter(prefix="/api/pantry", tags=["pantry"])


@router.get("", response_model=List[IngredientRead])
def list_ingredients(
    expiring_soon: bool = Query(False),
    db: Session = Depends(get_db)
):
    """List all ingredients. Optional query param ?expiring_soon=true filters to ingredients with expiry_date within 7 days from today."""
    query = db.query(Ingredient)

    if expiring_soon:
        today = datetime.utcnow().date()
        seven_days_later = today + timedelta(days=7)
        query = query.filter(
            (Ingredient.expiry_date >= today) & (Ingredient.expiry_date <= seven_days_later)
        )

    return query.all()


@router.get("/expiring", response_model=List[IngredientRead])
def list_expiring_ingredients(db: Session = Depends(get_db)):
    """Ingredients expiring within 7 days."""
    today = datetime.utcnow().date()
    seven_days_later = today + timedelta(days=7)

    return db.query(Ingredient).filter(
        (Ingredient.expiry_date >= today) & (Ingredient.expiry_date <= seven_days_later)
    ).all()


@router.post("", response_model=IngredientRead, status_code=status.HTTP_201_CREATED)
def create_ingredient(ingredient: IngredientCreate, db: Session = Depends(get_db)):
    """Create a new ingredient."""
    db_ingredient = Ingredient(**ingredient.model_dump())
    db.add(db_ingredient)
    db.commit()
    db.refresh(db_ingredient)
    return db_ingredient


@router.put("/{id}", response_model=IngredientRead)
def update_ingredient(id: int, ingredient: IngredientUpdate, db: Session = Depends(get_db)):
    """Update ingredient fields (partial update)."""
    db_ingredient = db.query(Ingredient).filter(Ingredient.id == id).first()
    if not db_ingredient:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Ingredient not found")

    update_data = ingredient.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_ingredient, field, value)

    db_ingredient.updated_at = datetime.utcnow()
    db.commit()
    db.refresh(db_ingredient)
    return db_ingredient


@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_ingredient(id: int, db: Session = Depends(get_db)):
    """Delete an ingredient."""
    db_ingredient = db.query(Ingredient).filter(Ingredient.id == id).first()
    if not db_ingredient:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Ingredient not found")

    db.delete(db_ingredient)
    db.commit()


@router.post("/bulk", response_model=List[IngredientRead])
def bulk_upsert_ingredients(ingredients: List[IngredientCreate], db: Session = Depends(get_db)):
    """Upsert list of ingredients. If an ingredient with same name exists, add the quantity (accumulate). If not, create new."""
    result = []

    for ingredient_data in ingredients:
        existing = db.query(Ingredient).filter(Ingredient.name == ingredient_data.name).first()

        if existing:
            existing.quantity += ingredient_data.quantity
            existing.updated_at = datetime.utcnow()
            db.commit()
            db.refresh(existing)
            result.append(existing)
        else:
            new_ingredient = Ingredient(**ingredient_data.model_dump())
            db.add(new_ingredient)
            db.commit()
            db.refresh(new_ingredient)
            result.append(new_ingredient)

    return result