Coverage for opt/mealie/lib/python3.12/site-packages/mealie/routes/households/controller_group_recipe_actions.py: 69%

55 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 15:32 +0000

1from functools import cached_property 1a

2 

3import requests 1a

4from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, status 1a

5from fastapi.encoders import jsonable_encoder 1a

6from pydantic import UUID4 1a

7 

8from mealie.core.exceptions import NoEntryFound 1a

9from mealie.routes._base.base_controllers import BaseUserController 1a

10from mealie.routes._base.controller import controller 1a

11from mealie.routes._base.mixins import HttpRepo 1a

12from mealie.schema.household.group_recipe_action import ( 1a

13 CreateGroupRecipeAction, 

14 GroupRecipeActionOut, 

15 GroupRecipeActionPagination, 

16 GroupRecipeActionPayload, 

17 GroupRecipeActionType, 

18 SaveGroupRecipeAction, 

19) 

20from mealie.schema.response import ErrorResponse 1a

21from mealie.schema.response.pagination import PaginationQuery 1a

22from mealie.services.recipe.recipe_service import RecipeService 1a

23 

24router = APIRouter(prefix="/households/recipe-actions", tags=["Households: Recipe Actions"]) 1a

25 

26 

27@controller(router) 1a

28class GroupRecipeActionController(BaseUserController): 1a

29 @cached_property 1a

30 def repo(self): 1a

31 return self.repos.group_recipe_actions 1lcfdeghijkb

32 

33 @property 1a

34 def mixins(self): 1a

35 return HttpRepo[CreateGroupRecipeAction, GroupRecipeActionOut, SaveGroupRecipeAction](self.repo, self.logger) 1cfdeghijkb

36 

37 # ================================================================================================================== 

38 # CRUD 

39 

40 @router.get("", response_model=GroupRecipeActionPagination) 1a

41 def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): 1a

42 response = self.repo.page_all( 1lcfdeghijkb

43 pagination=q, 

44 override=GroupRecipeActionOut, 

45 ) 

46 

47 response.set_pagination_guides(router.url_path_for("get_all"), q.model_dump()) 1lcfdeghijb

48 return response 1lcfdeghijb

49 

50 @router.post("", response_model=GroupRecipeActionOut, status_code=201) 1a

51 def create_one(self, data: CreateGroupRecipeAction): 1a

52 save = data.cast(SaveGroupRecipeAction, group_id=self.group_id, household_id=self.household_id) 1cfdeghijkb

53 return self.mixins.create_one(save) 1cfdeghijkb

54 

55 @router.get("/{item_id}", response_model=GroupRecipeActionOut) 1a

56 def get_one(self, item_id: UUID4): 1a

57 return self.mixins.get_one(item_id) 1db

58 

59 @router.put("/{item_id}", response_model=GroupRecipeActionOut) 1a

60 def update_one(self, item_id: UUID4, data: SaveGroupRecipeAction): 1a

61 return self.mixins.update_one(data, item_id) 

62 

63 @router.delete("/{item_id}", response_model=GroupRecipeActionOut) 1a

64 def delete_one(self, item_id: UUID4): 1a

65 return self.mixins.delete_one(item_id) 1ceb

66 

67 # ================================================================================================================== 

68 # Actions 

69 

70 @router.post("/{item_id}/trigger/{recipe_slug}", status_code=202) 1a

71 def trigger_action( 1a

72 self, item_id: UUID4, recipe_slug: str, bg_tasks: BackgroundTasks, recipe_scale: float = Body(1, embed=True) 

73 ) -> None: 

74 recipe_action = self.repos.group_recipe_actions.get_one(item_id) 

75 if not recipe_action: 

76 raise HTTPException( 

77 status.HTTP_404_NOT_FOUND, 

78 detail=ErrorResponse.respond(message="Not found."), 

79 ) 

80 

81 if recipe_action.action_type == GroupRecipeActionType.post.value: 

82 task_action = requests.post 

83 else: 

84 raise HTTPException( 

85 status.HTTP_400_BAD_REQUEST, 

86 detail=ErrorResponse.respond(message=f'Cannot trigger action type "{recipe_action.action_type}".'), 

87 ) 

88 

89 recipe_service = RecipeService(self.repos, self.user, self.household, translator=self.translator) 

90 try: 

91 recipe = recipe_service.get_one(recipe_slug) 

92 except NoEntryFound as e: 

93 raise HTTPException( 

94 status.HTTP_404_NOT_FOUND, 

95 detail=ErrorResponse.respond(message="Not found."), 

96 ) from e 

97 

98 payload = GroupRecipeActionPayload(action=recipe_action, content=recipe, recipe_scale=recipe_scale) 

99 bg_tasks.add_task( 

100 task_action, 

101 url=recipe_action.url, 

102 json=jsonable_encoder(payload.model_dump()), 

103 timeout=15, 

104 )