Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #3
0
    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)
Exemple #4
0
def api_entry():
    masonBuilder = MasonBuilder()
    masonBuilder.add_namespace("clicook", "/api/link-relations/")
    masonBuilder.add_control("clicook:recipes-all",
                             api.url_for(RecipeCollection),
                             title="Recipes")
    masonBuilder.add_control("clicook:food-items-all",
                             api.url_for(FoodItemCollection),
                             title="Food items")
    # TODO: ADD MISSING CONTROLS FOR API ENTRY
    return Response(json.dumps(masonBuilder), 200, mimetype=MASON)
Exemple #5
0
    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)
Exemple #6
0
 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)
Exemple #7
0
    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)
Exemple #8
0
    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
Exemple #9
0
    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
Exemple #10
0
    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)
Exemple #11
0
    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)
Exemple #12
0
    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
Exemple #13
0
    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
Exemple #14
0
    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
Exemple #15
0
    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
Exemple #16
0
    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
Exemple #17
0
    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