def get(self, recipe_id, ingredient_id): body = IngredientBuilder() body.add_namespace("clicook", "/api/link-relations/") ingredient = Ingredient.query.filter_by(id=ingredient_id).first() if ingredient is None: return MasonBuilder.get_error_response( 404, "Ingredient not found", "Ingredient with id {0} not found".format(ingredient_id)) body.add_control( "self", api.url_for(IngredientItem, recipe_id=recipe_id, ingredient_id=ingredient_id)) body.add_control_edit_ingredient(ingredient.recipe_id, ingredient.id) body.add_control_delete_ingredient(ingredient.recipe_id, ingredient.id) body.add_control("profile", "/api/profiles/") body["id"] = ingredient.id body["recipe_id"] = ingredient.recipe_id body["food_item_id"] = ingredient.food_item_id body["food_item_equivalent_id"] = ingredient.food_item_equivalent_id body["quantity"] = ingredient.quantity return Response(json.dumps(body), 200, mimetype=MASON)
def get(self, food_item_id, food_item_equivalent_id): body = FoodItemEquivalentBuilder() body.add_namespace("clicook", "/api/link-relations/") food_item_equivalent = FoodItemEquivalent.query.filter_by( id=food_item_equivalent_id).first() if food_item_equivalent is None: return MasonBuilder.get_error_response( 404, "Equivalent not found", "FoodItemEquivalent with id {0} not found".format( food_item_equivalent_id)) body.add_control( "self", api.url_for(FoodItemEquivalentResource, food_item_id=food_item_equivalent.food_item_id, food_item_equivalent_id=food_item_equivalent.id)) body.add_control_edit_food_item_equivalent( food_item_equivalent.food_item_id, food_item_equivalent.id) body.add_control_delete_food_item_equivalent( food_item_equivalent.food_item_id, food_item_equivalent.id) body.add_control("profile", "/api/profiles/") body["id"] = food_item_equivalent.id body["food_item_id"] = food_item_equivalent.food_item_id body["unit_type"] = food_item_equivalent.unit_type body["conversion_factor"] = food_item_equivalent.conversion_factor return Response(json.dumps(body), 200, mimetype=MASON)
def delete(self, food_item_id): food_item = FoodItem.query.filter_by(id=food_item_id).first() if food_item is None: return MasonBuilder.get_error_response( 404, "FoodItem not found.", "FoodItem with id {0} not found".format(food_item_id)) num_ingredient = Ingredient.query.filter_by( food_item_id=food_item_id).count() if num_ingredient > 0: return MasonBuilder.get_error_response( 409, "Cannot delete food item in use.", "FoodItem with is used for {0} ingredients".format( num_ingredient)) db.session.delete(food_item) db.session.commit() return Response(None, 204)
def delete(self, ingredient_id, recipe_id): ingredient = Ingredient.query.filter_by(id=ingredient_id).first() if ingredient is None: return MasonBuilder.get_error_response( 404, "Ingredient not found", "Ingredient with id {0} not found".format(ingredient_id)) db.session.delete(ingredient) db.session.commit() return Response(None, 204)
def delete(self, food_item_equivalent_id, food_item_id): food_item_equivalent = FoodItemEquivalent.query.filter_by( id=food_item_equivalent_id).first() if food_item_equivalent is None: return MasonBuilder.get_error_response( 404, "FoodItemEquivalent not found.", "FoodItemEquivalent with id {0} not found".format( food_item_equivalent_id)) db.session.delete(food_item_equivalent) db.session.commit() return Response(None, 204)
def delete(self, recipe_id): """ Delete recipe """ recipe = Recipe.query.filter_by(id=recipe_id).first() if recipe is None: return MasonBuilder.get_error_response( 404, "Recipe not found.", "Recipe with id {0} not found".format(recipe_id)) db.session.delete(recipe) db.session.commit() return Response(None, 204)
def post(self, food_item_id): """ Add food item equivalent """ if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") food_item = FoodItem.query.filter_by(id=food_item_id).first() if food_item is None: return MasonBuilder.get_error_response( 404, "Food item not found.", "FoodItem with id {0} not found".format(food_item_id)) equivalents = FoodItemEquivalent.query.filter_by( food_item_id=food_item.id).all() keys = request.json.keys() if not set(["unit_type", "conversion_factor"]).issubset(keys): return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", "") unit_type = request.json['unit_type'] if unit_type not in [e.value for e in EquivalentUnitType]: return MasonBuilder.get_error_response( 400, "Unknown unit type", "Unknown unit type {}".format(unit_type)) if unit_type in [e.unit_type for e in equivalents]: return MasonBuilder.get_error_response( 409, "Unit type is reserved", "Food item equivalent with unit type {} already exists".format( unit_type)) conversion_factor = 0 try: conversion_factor = float(request.json['conversion_factor']) if conversion_factor < 0: raise ValueError except ValueError: return MasonBuilder.get_error_response( 400, "Conversion factor must be a positive number", "") food_item_equivalent = FoodItemEquivalent( food_item_id=food_item.id, unit_type=unit_type, conversion_factor=conversion_factor) db.session.add(food_item_equivalent) db.session.commit() headers = { "Location": api.url_for(FoodItemEquivalentResource, food_item_id=food_item.id, food_item_equivalent_id=food_item_equivalent.id) } response = Response(None, 201, headers=headers) return response
def post(self): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") keys = request.json.keys() if 'name' not in keys: return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", ["Missing field:name"]) name = request.json['name'] if len(name) < 1: return MasonBuilder.get_error_response(400, "Name is too short", "") elif len(name) > 64: return MasonBuilder.get_error_response(400, "Name is too long", "") recipe = Recipe(name=name) db.session.add(recipe) db.session.commit() headers = {"Location": api.url_for(RecipeItem, recipe_id=recipe.id)} response = Response(status=201, headers=headers) return response
def get(self, recipe_id): body = RecipeBuilder() body.add_namespace("clicook", "/api/link-relations/") recipe = Recipe.query.filter_by(id=recipe_id).first() if recipe is None: return MasonBuilder.get_error_response( 404, "Recipe not found.", "Recipe with id {0} not found".format(recipe_id)) body.add_control("self", api.url_for(RecipeItem, recipe_id=recipe.id)) body.add_control_edit_recipe(recipe.id) body.add_control_delete_recipe(recipe.id) body.add_control_add_ingredient(recipe.id) body.add_control("collection", api.url_for(RecipeCollection)) body.add_control("profile", "/api/profiles/") body["name"] = recipe.name body["id"] = recipe.id items = [] body["emissions_total"] = 0.0 ingredients = Ingredient.query.filter_by(recipe_id=recipe_id).all() for ingredient in ingredients: item = IngredientBuilder() item["food_item_id"] = ingredient.food_item_id item["recipe_id"] = ingredient.recipe_id item[ "food_item_equivalent_id"] = ingredient.food_item_equivalent_id item["quantity"] = ingredient.quantity body["emissions_total"] += ingredient.food_item.emission_per_kg \ * ingredient.quantity \ * ingredient.food_item_equivalent.conversion_factor item.add_control( "self", api.url_for(IngredientItem, recipe_id=recipe_id, ingredient_id=ingredient.id)) item.add_control("profile", "/api/profiles/") items.append(item) body["items"] = items return Response(json.dumps(body), 200, mimetype=MASON)
def get(self, food_item_id): body = FoodItemBuilder() body.add_namespace("clicook", "/api/link-relations/") food_item = FoodItem.query.filter_by(id=food_item_id).first() if food_item is None: return MasonBuilder.get_error_response( 404, "Food item not found.", "FoodItem with id {0} not found".format(food_item_id)) body.add_control( "self", api.url_for(FoodItemResource, food_item_id=food_item.id)) body.add_control_edit_food_item(food_item.id) body.add_control_delete_food_item(food_item.id) body.add_control_add_food_item_equivalent(food_item.id) body.add_control("collection", api.url_for(FoodItemCollection)) body.add_control("profile", "/api/profiles/") # TODO: Add control for food-items with equivalents body["id"] = food_item.id body['name'] = food_item.name body['emission_per_kg'] = food_item.emission_per_kg body['vegan'] = food_item.vegan body['domestic'] = food_item.domestic body['organic'] = food_item.organic items = [] equivalents = FoodItemEquivalent.query.filter_by( food_item_id=food_item.id).all() for equivalent in equivalents: item = FoodItemEquivalentBuilder() item['unit_type'] = equivalent.unit_type item['conversion_factor'] = equivalent.conversion_factor item.add_control( "self", api.url_for(FoodItemEquivalentResource, food_item_id=food_item.id, food_item_equivalent_id=equivalent.id)) item.add_control('profile', '/api/profiles/') items.append(item) body["items"] = items return Response(json.dumps(body), 200, mimetype=MASON)
def put(self, recipe_id): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") recipe = Recipe.query.filter_by(id=recipe_id).first() if recipe is None: return MasonBuilder.get_error_response( 404, "Recipe not found.", "Recipe with id {0} not found".format(recipe_id)) keys = request.json.keys() if 'name' not in keys: return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", ["Missing field:name"]) name = request.json['name'] if len(name) < 1: return MasonBuilder.get_error_response(400, "Name is too short", "") elif len(name) > 64: return MasonBuilder.get_error_response(400, "Name is too long", "") recipe.name = name new_id = request.json['id'] if new_id is not None: if new_id != recipe.id and Recipe.query.filter_by( id=new_id).first() is not None: return MasonBuilder.get_error_response( 409, "Recipe id is already taken", "Recipe id {0} is already taken".format(new_id)) if new_id < 0: return MasonBuilder.get_error_response( 400, "Recipe id must be a positive integer", "") recipe.id = new_id db.session.commit() headers = {"Location": api.url_for(RecipeItem, recipe_id=recipe.id)} response = Response(None, 204, headers=headers) return response
def put(self, ingredient_id, recipe_id): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") ingredient = Ingredient.query.filter_by(id=ingredient_id).first() if ingredient is None: return MasonBuilder.get_error_response( 404, "Ingredient not found.", "Ingredient with id {0} not found".format(ingredient_id)) keys = request.json.keys() if not set([ "recipe_id", "food_item_id", "food_item_equivalent_id", "quantity" ]).issubset(keys): return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", "Missing fields") new_id = request.json['id'] if new_id is not None: if new_id != ingredient.id and Ingredient.query.filter_by( id=new_id).first() is not None: return MasonBuilder.get_error_response( 409, "Ingredient id is already taken", "Ingredient id {0} is already taken".format(new_id)) if new_id < 0: return MasonBuilder.get_error_response( 400, "Ingredient id must be a positive integer", "") ingredient.id = new_id new_food_item_id = request.json['food_item_id'] if new_food_item_id is not None: if new_food_item_id < 0: return MasonBuilder.get_error_response( 400, "FoodItem id must be a positive integer", "") ingredient.food_item_id = new_food_item_id new_food_item_equivalent_id = request.json['food_item_equivalent_id'] if new_food_item_equivalent_id is not None: if new_food_item_equivalent_id < 0: return MasonBuilder.get_error_response( 400, "FoodItemEquivalent id must be a positive integer", "") ingredient.food_item_equivalent_id = new_food_item_equivalent_id new_recipe_id = request.json['recipe_id'] if new_recipe_id is not None: if new_recipe_id < 0: return MasonBuilder.get_error_response( 400, "Recipe id must be a positive integer", "") ingredient.recipe_id = new_recipe_id quantity = 0 try: quantity = float(request.json["quantity"]) if quantity < 0: raise ValueError except ValueError: return MasonBuilder.get_error_response( 400, "Quantity must be a positive number", "") ingredient.quantity = quantity db.session.commit() headers = { "Location": api.url_for(IngredientItem, recipe_id=ingredient.recipe_id, ingredient_id=ingredient.id) } response = Response(None, 204, headers=headers) return response
def post(self, recipe_id): """ Add new ingredient to recipe """ if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") recipe = Recipe.query.filter_by(id=recipe_id).first() if recipe is None: return MasonBuilder.get_error_response( 404, "Recipe not found.", "Recipe with id {0} not found".format(recipe_id)) # ingredients = Ingredient.query.filter_by(recipe_id=recipe.id).all() keys = request.json.keys() if not set(["food_item_id", "food_item_equivalent_id", "quantity" ]).issubset(keys): return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", "") food_item = FoodItem.query.filter_by( id=request.json['food_item_id']).first() if food_item is None: return MasonBuilder.get_error_response( 404, "FoodItem not found.", "FoodItem with id {0} not found".format( request.json['food_item_id'])) food_item_equivalent = FoodItemEquivalent.query.filter_by(food_item_id=food_item.id) \ .filter_by(id=request.json['food_item_equivalent_id']).first() if food_item_equivalent is None: return MasonBuilder.get_error_response( 404, "FoodItemEquivalent not found.", "FoodItemEquivalent with id {0} not found".format( request.json['food_item_equivalent_id'])) quantity = 0 try: quantity = float(request.json['quantity']) if quantity <= 0: raise ValueError except ValueError: return MasonBuilder.get_error_response( 400, "Quantity must be a positive number", "") ingredient = Ingredient( recipe_id=recipe.id, food_item_id=food_item.id, food_item_equivalent_id=food_item_equivalent.id, quantity=quantity) db.session.add(ingredient) db.session.commit() headers = { "Location": api.url_for(IngredientItem, recipe_id=recipe.id, ingredient_id=ingredient.id) } response = Response(None, 201, headers=headers) return response
def post(self): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") required = FoodItemBuilder.food_item_schema()['required'] missing = [] for field in required: if field not in request.json.keys(): missing.append(field) if len(missing) > 0: details = [] for field in missing: details.append("Missing field:{0}".format(field)) return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", details) name = request.json['name'] if len(name) < 1: return MasonBuilder.get_error_response(400, "Name is too short", "") elif len(name) > 128: return MasonBuilder.get_error_response(400, "Name is too long", "") raw_emission_per_kg = request.json['emission_per_kg'] emission_per_kg = 0.0 try: emission_per_kg = float(raw_emission_per_kg) except ValueError: return MasonBuilder.get_error_response( 400, "emission_per_kg must be a number", "") if emission_per_kg < 0: return MasonBuilder.get_error_response( 400, "emission_per_kg must be a positive number", "") vegan = False if 'vegan' in request.json.keys( ) and request.json['vegan'] is not None: vegan = request.json['vegan'] organic = False if 'organic' in request.json.keys( ) and request.json['organic'] is not None: organic = request.json['organic'] domestic = False if 'domestic' in request.json.keys( ) and request.json['domestic'] is not None: domestic = request.json['domestic'] food_item = FoodItem(name=name, emission_per_kg=emission_per_kg, vegan=vegan, organic=organic, domestic=domestic) db.session.add(food_item) db.session.commit() headers = { "Location": api.url_for(FoodItemResource, food_item_id=food_item.id) } response = Response(status=201, headers=headers) return response
def put(self, food_item_id, food_item_equivalent_id): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") food_item_equivalent = FoodItemEquivalent.query.filter_by( id=food_item_equivalent_id).first() if food_item_equivalent is None: return MasonBuilder.get_error_response( 404, "Food item equivalent not found.", "FoodItemEquivalent with id {0} not found".format( food_item_equivalent_id)) keys = request.json.keys() if not set(["food_item_id", "unit_type", "conversion_factor" ]).issubset(keys): return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", "") unit_type = request.json['unit_type'] if unit_type not in [e.value for e in EquivalentUnitType]: return MasonBuilder.get_error_response( 400, "Unknown unit type", "Unknown unit type {}".format(unit_type)) food_item_equivalent.unit_type = unit_type conversion_factor = 0 try: conversion_factor = float(request.json['conversion_factor']) if conversion_factor < 0: raise ValueError except ValueError: return MasonBuilder.get_error_response( 400, "Conversion factor must be a positive number", "") food_item_equivalent.conversion_factor = conversion_factor if "food_item_id" in keys: try: new_food_item_id = int(request.json["food_item_id"]) if new_food_item_id is not None: if new_food_item_id < 0: return MasonBuilder.get_error_response( 400, "FoodItem id must be a positive integer", "") except ValueError: return MasonBuilder.get_error_response( 400, "FoodItem id must be a positive integer", "") if "id" in keys: try: new_id = int(request.json['id']) if new_id is not None: if new_id != food_item_equivalent.id and FoodItemEquivalent.query \ .filter_by(id=new_id).first() is not None: return MasonBuilder.get_error_response( 409, "FoodItemEquivalent id is already taken", "FoodItemEquivalent id {0} is already taken". format(new_id)) if new_id < 0: return MasonBuilder.get_error_response( 400, "FoodItemEquivalent id must be a positive integer", "") food_item_equivalent.id = new_id except ValueError: return MasonBuilder.get_error_response( 400, "FoodItemEquivalent id must be a positive integer", "") db.session.commit() headers = { "Location": api.url_for(FoodItemEquivalentResource, food_item_equivalent_id=food_item_equivalent.id, food_item_id=food_item_id) } response = Response(None, 204, headers=headers) return response
def put(self, food_item_id): if request.json is None: return MasonBuilder.get_error_response( 415, "Request content type must be JSON", "") food_item = FoodItem.query.filter_by(id=food_item_id).first() if food_item is None: return MasonBuilder.get_error_response( 404, "Food item not found.", "FoodItem with id {0} not found".format(food_item_id)) keys = request.json.keys() if 'name' not in keys: return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", ["Missing field:name"]) if 'emission_per_kg' not in keys: return MasonBuilder.get_error_response( 400, "Incomplete request - missing fields", ["Missing field:emission_per_kg"]) name = request.json['name'] if len(name) < 1: return MasonBuilder.get_error_response(400, "Name is too short", "") elif len(name) > 128: return MasonBuilder.get_error_response(400, "Name is too long", "") food_item.name = name emissions = 0 try: emissions = float(request.json['emission_per_kg']) if emissions < 0: raise ValueError except ValueError: return MasonBuilder.get_error_response( 400, "Emissions per kg must be a positive number", "") food_item.emission_per_kg = emissions if "id" in keys: try: new_id = int(request.json['id']) if new_id is not None: if new_id != food_item.id and FoodItem.query.filter_by( id=new_id).first() is not None: return MasonBuilder.get_error_response( 409, "FoodItem id is already taken", "FoodItem id {0} is already taken".format(new_id)) if new_id < 0: return MasonBuilder.get_error_response( 400, "FoodItem id must be a positive integer", "") food_item.id = new_id except ValueError: return MasonBuilder.get_error_response( 400, "FoodItem id must be a positive integer", "") if 'vegan' in request.json.keys() and type( request.json['vegan']) is bool: food_item.vegan = request.json['vegan'] if 'organic' in request.json.keys() and type( request.json['organic']) is bool: food_item.organic = request.json['organic'] if 'domestic' in request.json.keys() and type( request.json['domestic']) is bool: food_item.domestic = request.json['domestic'] db.session.commit() headers = { "Location": api.url_for(FoodItemResource, food_item_id=food_item.id) } response = Response(None, 204, headers=headers) return response