From c9bef353039181da8703dd34e24f3563b8e3be90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Doma=C5=84ski?= Date: Wed, 8 Apr 2026 19:31:48 +0200 Subject: [PATCH] [preset create] view for creating empty preset --- Makefile | 3 +++ doc/openapi.json | 2 +- fooder/model/preset.py | 4 ++++ fooder/test/view/test_preset.py | 19 +++++++++++++++++++ fooder/view/preset.py | 12 +++++++++++- 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 35b0c97..15516a4 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,9 @@ lint: black mypy flake version: @echo $(VERSION) +openapi: + @curl http://localhost:8000/openapi.json -o doc/openapi.json + create-venv: python3 -m venv .venv --prompt="fooderapi-venv" --system-site-packages bash -c "source .venv/bin/activate && pip install -r requirements/local.txt" diff --git a/doc/openapi.json b/doc/openapi.json index 0f7a37e..b5edc5d 100644 --- a/doc/openapi.json +++ b/doc/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"title":"Fooder","version":"0.1.0"},"paths":{"/api/token":{"post":{"tags":["token","token"],"summary":"Token Create","operationId":"token_create_api_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_create_api_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/token/refresh":{"post":{"tags":["token","token"],"summary":"Token Refresh","operationId":"token_refresh_api_token_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product":{"get":{"tags":["product","product"],"summary":"List Products","operationId":"list_products_api_product_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductModel"},"title":"Response List Products Api Product Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["product","product"],"summary":"Create Product","operationId":"create_product_api_product_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product/{product_id}":{"patch":{"tags":["product","product"],"summary":"Update Product","operationId":"update_product_api_product__product_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"integer","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product/barcode/{barcode}":{"get":{"tags":["product","product"],"summary":"Get By Barcode","operationId":"get_by_barcode_api_product_barcode__barcode__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"barcode","in":"path","required":true,"schema":{"type":"string","title":"Barcode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"post":{"tags":["user","user"],"summary":"User Create","operationId":"user_create_api_user_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreateModel"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/password":{"patch":{"tags":["user","user"],"summary":"User Change Password","operationId":"user_change_password_api_user_password_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserChangePasswordModel"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/user/settings":{"get":{"tags":["user_settings","user_settings"],"summary":"Get User Settings","operationId":"get_user_settings_api_user_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsModel"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["user_settings","user_settings"],"summary":"Update User Settings","operationId":"update_user_settings_api_user_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsUpdateModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/diary/{date}":{"get":{"tags":["diary","diary"],"summary":"Get Diary","operationId":"get_diary_api_diary__date__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["diary","diary"],"summary":"Update Diary","operationId":"update_diary_api_diary__date__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary":{"post":{"tags":["diary","diary"],"summary":"Create Diary Route","operationId":"create_diary_route_api_diary_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryCreateModel"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/diary/{date}/meal":{"post":{"tags":["meal","meal"],"summary":"Create Meal","operationId":"create_meal_api_diary__date__meal_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/from_preset":{"post":{"tags":["meal","meal"],"summary":"Load Preset As Meal View","operationId":"load_preset_as_meal_view_api_diary__date__meal_from_preset_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadPresetAsMealModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}":{"patch":{"tags":["meal","meal"],"summary":"Update Meal","operationId":"update_meal_api_diary__date__meal__meal_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["meal","meal"],"summary":"Delete Meal","operationId":"delete_meal_api_diary__date__meal__meal_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/preset":{"post":{"tags":["meal","meal"],"summary":"Save Meal As Preset View","operationId":"save_meal_as_preset_view_api_diary__date__meal__meal_id__preset_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAsPresetModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/entry":{"post":{"tags":["entry","entry"],"summary":"Create Entry Route","operationId":"create_entry_route_api_diary__date__meal__meal_id__entry_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/entry/{entry_id}":{"patch":{"tags":["entry","entry"],"summary":"Update Entry","operationId":"update_entry_api_diary__date__meal__meal_id__entry__entry_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["entry","entry"],"summary":"Delete Entry","operationId":"delete_entry_api_diary__date__meal__meal_id__entry__entry_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset":{"get":{"tags":["preset"],"summary":"List Presets","operationId":"list_presets_api_preset_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PresetModel"},"title":"Response List Presets Api Preset Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/{preset_id}":{"patch":{"tags":["preset"],"summary":"Update Preset","operationId":"update_preset_api_preset__preset_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["preset"],"summary":"Delete Preset","operationId":"delete_preset_api_preset__preset_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/{preset_id}/entry":{"post":{"tags":["preset"],"summary":"Create Preset Entry","operationId":"create_preset_entry_api_preset__preset_id__entry_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetEntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/{preset_id}/entry/{entry_id}":{"patch":{"tags":["preset"],"summary":"Update Preset Entry","operationId":"update_preset_entry_api_preset__preset_id__entry__entry_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetEntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["preset"],"summary":"Delete Preset Entry","operationId":"delete_preset_entry_api_preset__preset_id__entry__entry_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_token_create_api_token_post":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_token_create_api_token_post"},"DiaryCreateModel":{"properties":{"date":{"type":"string","format":"date","title":"Date"}},"type":"object","required":["date"],"title":"DiaryCreateModel"},"DiaryModel":{"properties":{"id":{"type":"integer","title":"Id"},"date":{"type":"string","format":"date","title":"Date"},"protein_goal":{"type":"number","minimum":0.0,"title":"Protein Goal"},"carb_goal":{"type":"number","minimum":0.0,"title":"Carb Goal"},"fat_goal":{"type":"number","minimum":0.0,"title":"Fat Goal"},"fiber_goal":{"type":"number","minimum":0.0,"title":"Fiber Goal"},"calories_goal":{"type":"number","minimum":0.0,"title":"Calories Goal"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"meals":{"items":{"$ref":"#/components/schemas/MealModel"},"type":"array","title":"Meals"}},"type":"object","required":["id","date","protein_goal","carb_goal","fat_goal","fiber_goal","calories_goal","protein","carb","fat","fiber","calories","meals"],"title":"DiaryModel"},"DiaryUpdateModel":{"properties":{"protein_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Protein Goal"},"carb_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Carb Goal"},"fat_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fat Goal"},"fiber_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fiber Goal"},"calories_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories Goal"}},"type":"object","title":"DiaryUpdateModel"},"EntryCreateModel":{"properties":{"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"}},"type":"object","required":["grams","product_id"],"title":"EntryCreateModel"},"EntryModel":{"properties":{"id":{"type":"integer","title":"Id"},"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"},"meal_id":{"type":"integer","title":"Meal Id"},"product":{"$ref":"#/components/schemas/ProductModel"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"}},"type":"object","required":["id","grams","product_id","meal_id","product","protein","carb","fat","fiber","calories"],"title":"EntryModel"},"EntryUpdateModel":{"properties":{"grams":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Grams"}},"type":"object","title":"EntryUpdateModel"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoadPresetAsMealModel":{"properties":{"preset_id":{"type":"integer","title":"Preset Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["preset_id"],"title":"LoadPresetAsMealModel"},"MealCreateModel":{"properties":{"name":{"type":"string","title":"Name"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"}},"type":"object","required":["name"],"title":"MealCreateModel"},"MealModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"order":{"type":"integer","minimum":0.0,"title":"Order"},"diary_id":{"type":"integer","title":"Diary Id"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"entries":{"items":{"$ref":"#/components/schemas/EntryModel"},"type":"array","title":"Entries"}},"type":"object","required":["id","name","order","diary_id","protein","carb","fat","fiber","calories","entries"],"title":"MealModel"},"MealUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"}},"type":"object","title":"MealUpdateModel"},"PresetEntryModel":{"properties":{"id":{"type":"integer","title":"Id"},"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"},"preset_id":{"type":"integer","title":"Preset Id"},"product":{"$ref":"#/components/schemas/ProductModel"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"}},"type":"object","required":["id","grams","product_id","preset_id","product","protein","carb","fat","fiber","calories"],"title":"PresetEntryModel"},"PresetModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"user_id":{"type":"integer","title":"User Id"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"entries":{"items":{"$ref":"#/components/schemas/PresetEntryModel"},"type":"array","title":"Entries"}},"type":"object","required":["id","name","user_id","protein","carb","fat","fiber","calories","entries"],"title":"PresetModel"},"PresetUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"PresetUpdateModel"},"ProductCreateModel":{"properties":{"name":{"type":"string","title":"Name"},"protein":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Protein"},"carb":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Carb"},"fat":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fat"},"fiber":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fiber"},"calories":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","required":["name","protein","carb","fat","fiber"],"title":"ProductCreateModel"},"ProductModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"protein":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Protein"},"carb":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Carb"},"fat":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fat"},"fiber":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fiber"},"calories":{"type":"number","minimum":0.0,"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","required":["id","name","protein","carb","fat","fiber","calories"],"title":"ProductModel"},"ProductUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"protein":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Protein"},"carb":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Carb"},"fat":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Fat"},"fiber":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Fiber"},"calories":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","title":"ProductUpdateModel"},"RefreshTokenRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshTokenRequest"},"SaveAsPresetModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"SaveAsPresetModel"},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse"},"UserChangePasswordModel":{"properties":{"current_password":{"type":"string","title":"Current Password"},"new_password":{"type":"string","maxLength":128,"minLength":8,"title":"New Password"}},"type":"object","required":["current_password","new_password"],"title":"UserChangePasswordModel"},"UserCreateModel":{"properties":{"username":{"type":"string","maxLength":64,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"},"captcha_token":{"type":"string","title":"Captcha Token"}},"type":"object","required":["username","password","captcha_token"],"title":"UserCreateModel"},"UserSettingsModel":{"properties":{"id":{"type":"integer","title":"Id"},"protein_goal":{"type":"number","minimum":0.0,"title":"Protein Goal"},"carb_goal":{"type":"number","minimum":0.0,"title":"Carb Goal"},"fat_goal":{"type":"number","minimum":0.0,"title":"Fat Goal"},"fiber_goal":{"type":"number","minimum":0.0,"title":"Fiber Goal"},"calories_goal":{"type":"number","minimum":0.0,"title":"Calories Goal"}},"type":"object","required":["id","protein_goal","carb_goal","fat_goal","fiber_goal","calories_goal"],"title":"UserSettingsModel"},"UserSettingsUpdateModel":{"properties":{"protein_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Protein Goal"},"carb_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Carb Goal"},"fat_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fat Goal"},"fiber_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fiber Goal"},"calories_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories Goal"}},"type":"object","title":"UserSettingsUpdateModel"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"/token"}}}}}} \ No newline at end of file +{"openapi":"3.1.0","info":{"title":"Fooder","version":"0.1.0"},"paths":{"/api/token":{"post":{"tags":["token","token"],"summary":"Token Create","operationId":"token_create_api_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_create_api_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/token/refresh":{"post":{"tags":["token","token"],"summary":"Token Refresh","operationId":"token_refresh_api_token_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product":{"get":{"tags":["product","product"],"summary":"List Products","operationId":"list_products_api_product_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductModel"},"title":"Response List Products Api Product Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["product","product"],"summary":"Create Product","operationId":"create_product_api_product_post","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product/{product_id}":{"patch":{"tags":["product","product"],"summary":"Update Product","operationId":"update_product_api_product__product_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"integer","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/product/barcode/{barcode}":{"get":{"tags":["product","product"],"summary":"Get By Barcode","operationId":"get_by_barcode_api_product_barcode__barcode__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"barcode","in":"path","required":true,"schema":{"type":"string","title":"Barcode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user":{"post":{"tags":["user","user"],"summary":"User Create","operationId":"user_create_api_user_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreateModel"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user/password":{"patch":{"tags":["user","user"],"summary":"User Change Password","operationId":"user_change_password_api_user_password_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserChangePasswordModel"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/user/settings":{"get":{"tags":["user_settings","user_settings"],"summary":"Get User Settings","operationId":"get_user_settings_api_user_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsModel"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["user_settings","user_settings"],"summary":"Update User Settings","operationId":"update_user_settings_api_user_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsUpdateModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/diary/{date}":{"get":{"tags":["diary","diary"],"summary":"Get Diary","operationId":"get_diary_api_diary__date__get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["diary","diary"],"summary":"Update Diary","operationId":"update_diary_api_diary__date__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary":{"post":{"tags":["diary","diary"],"summary":"Create Diary Route","operationId":"create_diary_route_api_diary_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryCreateModel"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/diary/{date}/meal":{"post":{"tags":["meal","meal"],"summary":"Create Meal","operationId":"create_meal_api_diary__date__meal_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/from_preset":{"post":{"tags":["meal","meal"],"summary":"Load Preset As Meal View","operationId":"load_preset_as_meal_view_api_diary__date__meal_from_preset_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadPresetAsMealModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}":{"patch":{"tags":["meal","meal"],"summary":"Update Meal","operationId":"update_meal_api_diary__date__meal__meal_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["meal","meal"],"summary":"Delete Meal","operationId":"delete_meal_api_diary__date__meal__meal_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/preset":{"post":{"tags":["meal","meal"],"summary":"Save Meal As Preset View","operationId":"save_meal_as_preset_view_api_diary__date__meal__meal_id__preset_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAsPresetModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/entry":{"post":{"tags":["entry","entry"],"summary":"Create Entry Route","operationId":"create_entry_route_api_diary__date__meal__meal_id__entry_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary/{date}/meal/{meal_id}/entry/{entry_id}":{"patch":{"tags":["entry","entry"],"summary":"Update Entry","operationId":"update_entry_api_diary__date__meal__meal_id__entry__entry_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["entry","entry"],"summary":"Delete Entry","operationId":"delete_entry_api_diary__date__meal__meal_id__entry__entry_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Date"}},{"name":"meal_id","in":"path","required":true,"schema":{"type":"integer","title":"Meal Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset":{"get":{"tags":["preset"],"summary":"List Presets","operationId":"list_presets_api_preset_get","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PresetModel"},"title":"Response List Presets Api Preset Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/":{"post":{"tags":["preset"],"summary":"Create Preset","operationId":"create_preset_api_preset__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetCreateModel"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/preset/{preset_id}":{"patch":{"tags":["preset"],"summary":"Update Preset","operationId":"update_preset_api_preset__preset_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["preset"],"summary":"Delete Preset","operationId":"delete_preset_api_preset__preset_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/{preset_id}/entry":{"post":{"tags":["preset"],"summary":"Create Preset Entry","operationId":"create_preset_entry_api_preset__preset_id__entry_post","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryCreateModel"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetEntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preset/{preset_id}/entry/{entry_id}":{"patch":{"tags":["preset"],"summary":"Update Preset Entry","operationId":"update_preset_entry_api_preset__preset_id__entry__entry_id__patch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryUpdateModel"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetEntryModel"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["preset"],"summary":"Delete Preset Entry","operationId":"delete_preset_entry_api_preset__preset_id__entry__entry_id__delete","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"integer","title":"Preset Id"}},{"name":"entry_id","in":"path","required":true,"schema":{"type":"integer","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_token_create_api_token_post":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_token_create_api_token_post"},"DiaryCreateModel":{"properties":{"date":{"type":"string","format":"date","title":"Date"}},"type":"object","required":["date"],"title":"DiaryCreateModel"},"DiaryModel":{"properties":{"id":{"type":"integer","title":"Id"},"date":{"type":"string","format":"date","title":"Date"},"protein_goal":{"type":"number","minimum":0.0,"title":"Protein Goal"},"carb_goal":{"type":"number","minimum":0.0,"title":"Carb Goal"},"fat_goal":{"type":"number","minimum":0.0,"title":"Fat Goal"},"fiber_goal":{"type":"number","minimum":0.0,"title":"Fiber Goal"},"calories_goal":{"type":"number","minimum":0.0,"title":"Calories Goal"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"meals":{"items":{"$ref":"#/components/schemas/MealModel"},"type":"array","title":"Meals"}},"type":"object","required":["id","date","protein_goal","carb_goal","fat_goal","fiber_goal","calories_goal","protein","carb","fat","fiber","calories","meals"],"title":"DiaryModel"},"DiaryUpdateModel":{"properties":{"protein_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Protein Goal"},"carb_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Carb Goal"},"fat_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fat Goal"},"fiber_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fiber Goal"},"calories_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories Goal"}},"type":"object","title":"DiaryUpdateModel"},"EntryCreateModel":{"properties":{"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"}},"type":"object","required":["grams","product_id"],"title":"EntryCreateModel"},"EntryModel":{"properties":{"id":{"type":"integer","title":"Id"},"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"},"meal_id":{"type":"integer","title":"Meal Id"},"product":{"$ref":"#/components/schemas/ProductModel"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"}},"type":"object","required":["id","grams","product_id","meal_id","product","protein","carb","fat","fiber","calories"],"title":"EntryModel"},"EntryUpdateModel":{"properties":{"grams":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Grams"}},"type":"object","title":"EntryUpdateModel"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoadPresetAsMealModel":{"properties":{"preset_id":{"type":"integer","title":"Preset Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["preset_id"],"title":"LoadPresetAsMealModel"},"MealCreateModel":{"properties":{"name":{"type":"string","title":"Name"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"}},"type":"object","required":["name"],"title":"MealCreateModel"},"MealModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"order":{"type":"integer","minimum":0.0,"title":"Order"},"diary_id":{"type":"integer","title":"Diary Id"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"entries":{"items":{"$ref":"#/components/schemas/EntryModel"},"type":"array","title":"Entries"}},"type":"object","required":["id","name","order","diary_id","protein","carb","fat","fiber","calories","entries"],"title":"MealModel"},"MealUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"}},"type":"object","title":"MealUpdateModel"},"PresetCreateModel":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"PresetCreateModel"},"PresetEntryModel":{"properties":{"id":{"type":"integer","title":"Id"},"grams":{"type":"number","exclusiveMinimum":0.0,"title":"Grams"},"product_id":{"type":"integer","title":"Product Id"},"preset_id":{"type":"integer","title":"Preset Id"},"product":{"$ref":"#/components/schemas/ProductModel"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"}},"type":"object","required":["id","grams","product_id","preset_id","product","protein","carb","fat","fiber","calories"],"title":"PresetEntryModel"},"PresetModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"user_id":{"type":"integer","title":"User Id"},"protein":{"type":"number","title":"Protein"},"carb":{"type":"number","title":"Carb"},"fat":{"type":"number","title":"Fat"},"fiber":{"type":"number","title":"Fiber"},"calories":{"type":"number","title":"Calories"},"entries":{"items":{"$ref":"#/components/schemas/PresetEntryModel"},"type":"array","title":"Entries"}},"type":"object","required":["id","name","user_id","protein","carb","fat","fiber","calories","entries"],"title":"PresetModel"},"PresetUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"PresetUpdateModel"},"ProductCreateModel":{"properties":{"name":{"type":"string","title":"Name"},"protein":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Protein"},"carb":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Carb"},"fat":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fat"},"fiber":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fiber"},"calories":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","required":["name","protein","carb","fat","fiber"],"title":"ProductCreateModel"},"ProductModel":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"protein":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Protein"},"carb":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Carb"},"fat":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fat"},"fiber":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Fiber"},"calories":{"type":"number","minimum":0.0,"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","required":["id","name","protein","carb","fat","fiber","calories"],"title":"ProductModel"},"ProductUpdateModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"protein":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Protein"},"carb":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Carb"},"fat":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Fat"},"fiber":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Fiber"},"calories":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"}},"type":"object","title":"ProductUpdateModel"},"RefreshTokenRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshTokenRequest"},"SaveAsPresetModel":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"SaveAsPresetModel"},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse"},"UserChangePasswordModel":{"properties":{"current_password":{"type":"string","title":"Current Password"},"new_password":{"type":"string","maxLength":128,"minLength":8,"title":"New Password"}},"type":"object","required":["current_password","new_password"],"title":"UserChangePasswordModel"},"UserCreateModel":{"properties":{"username":{"type":"string","maxLength":64,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"},"captcha_token":{"type":"string","title":"Captcha Token"}},"type":"object","required":["username","password","captcha_token"],"title":"UserCreateModel"},"UserSettingsModel":{"properties":{"id":{"type":"integer","title":"Id"},"protein_goal":{"type":"number","minimum":0.0,"title":"Protein Goal"},"carb_goal":{"type":"number","minimum":0.0,"title":"Carb Goal"},"fat_goal":{"type":"number","minimum":0.0,"title":"Fat Goal"},"fiber_goal":{"type":"number","minimum":0.0,"title":"Fiber Goal"},"calories_goal":{"type":"number","minimum":0.0,"title":"Calories Goal"}},"type":"object","required":["id","protein_goal","carb_goal","fat_goal","fiber_goal","calories_goal"],"title":"UserSettingsModel"},"UserSettingsUpdateModel":{"properties":{"protein_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Protein Goal"},"carb_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Carb Goal"},"fat_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fat Goal"},"fiber_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Fiber Goal"},"calories_goal":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Calories Goal"}},"type":"object","title":"UserSettingsUpdateModel"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"/token"}}}}}} \ No newline at end of file diff --git a/fooder/model/preset.py b/fooder/model/preset.py index d74d99a..2ec0cbd 100644 --- a/fooder/model/preset.py +++ b/fooder/model/preset.py @@ -23,6 +23,10 @@ class PresetUpdateModel(BaseModel): name: str | None = None +class PresetCreateModel(BaseModel): + name: str + + class LoadPresetAsMealModel(BaseModel): preset_id: int name: str | None = None diff --git a/fooder/test/view/test_preset.py b/fooder/test/view/test_preset.py index c4f14be..81e408e 100644 --- a/fooder/test/view/test_preset.py +++ b/fooder/test/view/test_preset.py @@ -92,6 +92,25 @@ async def test_list_presets_without_auth_returns_401(client): assert response.status_code == 401 +# --- create preset --- + + +async def test_create_preset_returns_201(auth_client): + response = await auth_client.post("/api/preset/", json={"name": "Preset name"}) + assert response.status_code == 201 + + +async def test_create_preset_sets_name(auth_client): + response = await auth_client.post("/api/preset/", json={"name": "Preset name"}) + assert response.status_code == 201 + assert response.json()["name"] == "Preset name" + + +async def test_create_preset_without_auth_returns_401(client): + response = await client.post("/api/preset/", json={"name": "x"}) + assert response.status_code == 401 + + # --- update preset --- diff --git a/fooder/view/preset.py b/fooder/view/preset.py index fc8367f..47ee5a0 100644 --- a/fooder/view/preset.py +++ b/fooder/view/preset.py @@ -4,7 +4,7 @@ from fooder.context import AuthContextDependency, Context from fooder.controller.preset import PresetController from fooder.controller.preset_entry import PresetEntryController from fooder.model.entry import EntryCreateModel, EntryUpdateModel -from fooder.model.preset import PresetModel, PresetUpdateModel +from fooder.model.preset import PresetCreateModel, PresetModel, PresetUpdateModel from fooder.model.preset_entry import PresetEntryModel router = APIRouter() @@ -23,6 +23,16 @@ async def list_presets( ) +@router.post("/", response_model=PresetModel, status_code=201) +async def create_preset( + data: PresetCreateModel, + ctx: Context = Depends(_auth_ctx), +): + async with ctx.repo.transaction(): + ctrl = await PresetController.create(ctx, data.name) + return ctrl.obj + + @router.patch("/{preset_id}", response_model=PresetModel) async def update_preset( preset_id: int,