mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-11 04:45:22 -05:00
feat: merge food into another (#1143)
* setup food repository * add merge route and payloads * remove type checking * generate types * implement merge dialog * food repo tests * split install from workflow * bum dependencies * revert changes * update copy * refactor URLs to avoid incorrect template being used * stick advanced items under developer mode * use utility component for advanced feature
This commit is contained in:
@@ -27,6 +27,7 @@ from mealie.db.models.recipe.tool import Tool
|
||||
from mealie.db.models.server.task import ServerTaskModel
|
||||
from mealie.db.models.users import LongLiveToken, User
|
||||
from mealie.db.models.users.password_reset import PasswordResetModel
|
||||
from mealie.repos.repository_foods import RepositoryFood
|
||||
from mealie.repos.repository_meal_plan_rules import RepositoryMealPlanRules
|
||||
from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||
from mealie.schema.group.group_events import GroupEventNotifierOut
|
||||
@@ -94,8 +95,8 @@ class AllRepositories:
|
||||
return RepositoryRecipes(self.session, PK_SLUG, RecipeModel, Recipe)
|
||||
|
||||
@cached_property
|
||||
def ingredient_foods(self) -> RepositoryGeneric[IngredientFood, IngredientFoodModel]:
|
||||
return RepositoryGeneric(self.session, PK_ID, IngredientFoodModel, IngredientFood)
|
||||
def ingredient_foods(self) -> RepositoryFood:
|
||||
return RepositoryFood(self.session, PK_ID, IngredientFoodModel, IngredientFood)
|
||||
|
||||
@cached_property
|
||||
def ingredient_units(self) -> RepositoryGeneric[IngredientUnit, IngredientUnitModel]:
|
||||
|
||||
32
mealie/repos/repository_foods.py
Normal file
32
mealie/repos/repository_foods.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.db.models.recipe.ingredient import IngredientFoodModel
|
||||
from mealie.schema.recipe.recipe_ingredient import IngredientFood
|
||||
|
||||
from .repository_generic import RepositoryGeneric
|
||||
|
||||
|
||||
class RepositoryFood(RepositoryGeneric[IngredientFood, IngredientFoodModel]):
|
||||
def merge(self, from_food: UUID4, to_food: UUID4) -> IngredientFood | None:
|
||||
|
||||
from_model: IngredientFoodModel = (
|
||||
self.session.query(self.sql_model).filter_by(**self._filter_builder(**{"id": from_food})).one()
|
||||
)
|
||||
|
||||
to_model: IngredientFoodModel = (
|
||||
self.session.query(self.sql_model).filter_by(**self._filter_builder(**{"id": to_food})).one()
|
||||
)
|
||||
|
||||
to_model.ingredients += from_model.ingredients
|
||||
|
||||
try:
|
||||
self.session.delete(from_model)
|
||||
self.session.commit()
|
||||
except Exception as e:
|
||||
self.session.rollback()
|
||||
raise e
|
||||
|
||||
return self.get_one(to_food)
|
||||
|
||||
def by_group(self, group_id: UUID4) -> "RepositoryFood":
|
||||
return super().by_group(group_id) # type: ignore
|
||||
@@ -1,6 +1,6 @@
|
||||
from functools import cached_property
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
@@ -8,7 +8,13 @@ from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.query import GetAll
|
||||
from mealie.schema.recipe.recipe_ingredient import CreateIngredientFood, IngredientFood, SaveIngredientFood
|
||||
from mealie.schema.recipe.recipe_ingredient import (
|
||||
CreateIngredientFood,
|
||||
IngredientFood,
|
||||
IngredientMerge,
|
||||
SaveIngredientFood,
|
||||
)
|
||||
from mealie.schema.response.responses import SuccessResponse
|
||||
|
||||
router = APIRouter(prefix="/foods", tags=["Recipes: Foods"])
|
||||
|
||||
@@ -27,6 +33,15 @@ class IngredientFoodsController(BaseUserController):
|
||||
self.registered_exceptions,
|
||||
)
|
||||
|
||||
@router.put("/merge", response_model=SuccessResponse)
|
||||
def merge_one(self, data: IngredientMerge):
|
||||
try:
|
||||
self.repo.merge(data.from_food, data.to_food)
|
||||
return SuccessResponse.respond("Successfully merged foods")
|
||||
except Exception as e:
|
||||
self.deps.logger.error(e)
|
||||
raise HTTPException(500, "Failed to merge foods") from e
|
||||
|
||||
@router.get("", response_model=list[IngredientFood])
|
||||
def get_all(self, q: GetAll = Depends(GetAll)):
|
||||
return self.repo.get_all(start=q.start, limit=q.limit)
|
||||
|
||||
@@ -95,6 +95,11 @@ class IngredientRequest(MealieModel):
|
||||
ingredient: str
|
||||
|
||||
|
||||
class IngredientMerge(MealieModel):
|
||||
from_food: UUID4
|
||||
to_food: UUID4
|
||||
|
||||
|
||||
from mealie.schema.labels.multi_purpose_label import MultiPurposeLabelSummary
|
||||
|
||||
IngredientFood.update_forward_refs()
|
||||
|
||||
Reference in New Issue
Block a user