Skip to content

Commit

Permalink
feat: refrigerator feature
Browse files Browse the repository at this point in the history
  • Loading branch information
sspzoa committed Oct 11, 2024
1 parent e1178e4 commit 0ba6010
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 10 deletions.
1 change: 1 addition & 0 deletions app/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
recipe_collection = db.recipes
cooking_step_collection = db.cooking_steps
ingredient_collection = db.ingredients
refrigerator_collection = db.refrigerator
8 changes: 5 additions & 3 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from app.dependencies.auth import verify_token
from app.routes import ping, root
from app.routes.recipe import recipe, ingredient, cooking_step
from app.routes.refrigerator import ingredient_detect
from app.routes.recipe import recipe, ingredient_info, cooking_step
from app.routes.refrigerator import ingredient_detect, refrigerator

app = FastAPI(
title="Deening API",
Expand All @@ -30,6 +30,8 @@

# Protected routes
app.include_router(recipe.router, dependencies=[Depends(verify_token)])
app.include_router(ingredient.router, dependencies=[Depends(verify_token)])
app.include_router(ingredient_info.router, dependencies=[Depends(verify_token)])
app.include_router(cooking_step.router, dependencies=[Depends(verify_token)])
app.include_router(ingredient_detect.router, dependencies=[Depends(verify_token)])

app.include_router(refrigerator.router, dependencies=[Depends(verify_token)])
File renamed without changes.
48 changes: 48 additions & 0 deletions app/models/refrigerator/refrigerator_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import List

from pydantic import BaseModel


class Ingredient(BaseModel):
id: str
name: str
amount: float
unit: str
category: str


class AddIngredientForm(BaseModel):
name: str
amount: float
unit: str
category: str


class AddIngredientRequest(BaseModel):
ingredients: List[AddIngredientForm]


class AddIngredientResponse(BaseModel):
message: str


class DeleteIngredientResponse(BaseModel):
message: str


class IngredientCategory(BaseModel):
category: str
ingredients: List[Ingredient]


class Refrigerator(BaseModel):
categories: List[IngredientCategory]


class GetIngredientsResponse(BaseModel):
refrigerator: Refrigerator


class GetIngredientsByCategoryResponse(BaseModel):
category: str
ingredients: List[Ingredient]
4 changes: 2 additions & 2 deletions app/routes/recipe/cooking_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
router = APIRouter()


@router.post("/cooking_step", tags=["Recipe"], response_model=CookingStepResponse,
@router.post("/recipe/cooking_step", tags=["Recipe"], response_model=CookingStepResponse,
responses={400: {"model": ErrorResponse}, 404: {"model": ErrorResponse}})
async def get_or_create_cooking_step_info(request: CookingStepRequest):
async def get_cooking_step_info(request: CookingStepRequest):
"""
레시피의 특정 조리 단계에 대한 상세 정보를 반환하거나 생성합니다.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
from app.config import client as openai_client
from app.database import ingredient_collection
from app.models.error_models import ErrorResponse
from app.models.recipe.ingredient_models import IngredientRequest, Ingredient, IngredientResponse
from app.models.recipe.ingredient_info_models import IngredientRequest, Ingredient, IngredientResponse
from app.utils.image_utils import download_and_encode_image

router = APIRouter()


@router.post("/ingredient", tags=["Recipe"], response_model=IngredientResponse,
@router.post("/recipe/ingredient-info", tags=["Recipe"], response_model=IngredientResponse,
responses={400: {"model": ErrorResponse}})
async def get_or_create_ingredient(request: IngredientRequest):
async def get_ingredient_info(request: IngredientRequest):
"""
식재료 이름으로 검색하여 정보를 반환하거나, 없으면 새로 생성합니다.
"""
Expand Down
2 changes: 1 addition & 1 deletion app/routes/recipe/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


@router.post("/recipe", tags=["Recipe"], response_model=RecipeResponse, responses={400: {"model": ErrorResponse}})
async def get_or_create_recipe(request: RecipeRequest):
async def get_recipe(request: RecipeRequest):
"""
주어진 음식 이름에 대한 레시피를 검색하거나 생성합니다.
"""
Expand Down
2 changes: 1 addition & 1 deletion app/routes/refrigerator/ingredient_detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
router = APIRouter()


@router.post("/ingredient_detect", tags=["Refrigerator"],
@router.post("/refrigerator/ingredient_detect", tags=["Refrigerator"],
response_model=IngredientDetectResponse,
responses={400: {"model": ErrorResponse}, 404: {"model": NoIngredientsFoundResponse}})
async def ingredient_detect(image: UploadFile = File(...)):
Expand Down
94 changes: 94 additions & 0 deletions app/routes/refrigerator/refrigerator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from itertools import groupby

from bson import ObjectId
from fastapi import HTTPException, APIRouter

from app.database import refrigerator_collection
from app.models.error_models import ErrorResponse
from app.models.refrigerator.refrigerator_models import GetIngredientsResponse, Ingredient, IngredientCategory, \
Refrigerator, AddIngredientResponse, AddIngredientRequest, DeleteIngredientResponse

router = APIRouter()


@router.get("/refrigerator/ingredients", tags=["Refrigerator"], response_model=GetIngredientsResponse)
async def get_ingredients():
"""
냉장고에 있는 모든 재료의 리스트를 카테고리별로 묶어 반환합니다.
재료가 없을 경우 빈 배열을 반환합니다.
"""
try:
ingredients = await refrigerator_collection.find().to_list(length=None)

# 재료가 없을 경우 빈 Refrigerator 객체 반환
if not ingredients:
return GetIngredientsResponse(refrigerator=Refrigerator(categories=[]))

# 카테고리별로 정렬
sorted_ingredients = sorted(ingredients, key=lambda x: x["category"])

# 카테고리별로 그룹화
grouped_ingredients = []
for category, items in groupby(sorted_ingredients, key=lambda x: x["category"]):
category_ingredients = [Ingredient(id=str(item["_id"]), **item) for item in items]
grouped_ingredients.append(IngredientCategory(category=category, ingredients=category_ingredients))

refrigerator = Refrigerator(categories=grouped_ingredients)
return GetIngredientsResponse(refrigerator=refrigerator)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))


@router.put("/refrigerator/ingredients", tags=["Refrigerator"], responses={400: {"model": ErrorResponse}},
response_model=AddIngredientResponse)
async def add_ingredients(request: AddIngredientRequest):
"""
냉장고에 여러 재료를 추가합니다. 이미 존재하는 재료의 경우 양을 더합니다.
"""
try:
for ingredient in request.ingredients:
# 기존 재료 찾기
existing_ingredient = await refrigerator_collection.find_one(
{"name": ingredient.name, "category": ingredient.category})

if existing_ingredient:
# 이미 존재하는 재료라면 양을 더함
new_amount = existing_ingredient["amount"] + ingredient.amount
await refrigerator_collection.update_one(
{"name": ingredient.name, "category": ingredient.category},
{"$set": {"amount": new_amount}}
)
else:
# 새로운 재료라면 추가
await refrigerator_collection.insert_one(ingredient.dict())

return {"message": "재료가 성공적으로 추가되었습니다."}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))


@router.delete("/refrigerator/ingredient/{ingredient_id}", tags=["Refrigerator"],
response_model=DeleteIngredientResponse,
responses={400: {"model": ErrorResponse}, 404: {"model": ErrorResponse}})
async def delete_ingredient(ingredient_id: str):
"""
주어진 ID로 냉장고에서 재료를 삭제합니다.
"""
try:
# ObjectId로 변환
object_id = ObjectId(ingredient_id)
except:
raise HTTPException(status_code=404, detail="유효하지 않은 재료 ID입니다.")

try:
# 재료 삭제
result = await refrigerator_collection.delete_one({"_id": object_id})

if result.deleted_count == 0:
raise HTTPException(status_code=404, detail="해당 ID의 재료를 찾을 수 없습니다.")

return {"message": "재료가 성공적으로 삭제되었습니다."}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))

0 comments on commit 0ba6010

Please sign in to comment.