from werkzeug.exceptions import BadRequest, NotFound from sqlalchemy.exc import IntegrityError from flaschengeist import logger from flaschengeist.config import config from flaschengeist.database import db from .models import Drink, DrinkPrice, Ingredient, Tag, DrinkType, DrinkPriceVolume, DrinkIngredient, ExtraIngredient from flaschengeist.utils.picture import save_picture, get_picture, delete_picture from uuid import uuid4 def update(): db.session.commit() def get_tags(): return Tag.query.all() def get_tag(identifier): if isinstance(identifier, int): retVal = Tag.query.get(identifier) elif isinstance(identifier, str): retVal = Tag.query.filter(Tag.name == identifier).one_or_none() else: logger.debug("Invalid identifier type for Tag") raise BadRequest if not retVal: raise NotFound return retVal def create_tag(name): try: tag = Tag(name=name) db.session.add(tag) update() return tag except IntegrityError: raise BadRequest("Name already exists") def rename_tag(identifier, new_name): tag = get_tag(identifier) tag.name = new_name try: update() except IntegrityError: raise BadRequest("Name already exists") def delete_tag(identifier): tag = get_tag(identifier) db.session.delete(tag) try: update() except IntegrityError: raise BadRequest("Tag still in use") def get_drink_types(): return DrinkType.query.all() def get_drink_type(identifier): if isinstance(identifier, int): retVal = DrinkType.query.get(identifier) elif isinstance(identifier, str): retVal = DrinkType.query.filter(Tag.name == identifier).one_or_none() else: logger.debug("Invalid identifier type for DrinkType") raise BadRequest if not retVal: raise NotFound return retVal def create_drink_type(name): try: drinkType = DrinkType(name=name) db.session.add(drinkType) update() return drinkType except IntegrityError: raise BadRequest("Name already exists") def rename_drink_type(identifier, new_name): drink_type = get_drink_type(identifier) drink_type.name = new_name try: update() except IntegrityError: raise BadRequest("Name already exists") return drink_type def delete_drink_type(identifier): drinkType = get_drink_type(identifier) db.session.delete(drinkType) try: update() except IntegrityError: raise BadRequest("DrinkType still in use") def get_drinks(name=None): if name: return Drink.query.filter(Drink.name.contains(name)).all() return Drink.query.all() def get_drink(identifier): if isinstance(identifier, int): return Drink.query.get(identifier) elif isinstance(identifier, str): return Drink.query.filter(Tag.name == identifier).one_or_none() else: logger.debug("Invalid identifier type for Drink") raise BadRequest raise NotFound def set_drink(data): return update_drink(-1, data) def update_drink(identifier, data): allowedKeys = Drink().serialize().keys() if "id" in data: data.pop("id") if "volumes" in data: volumes = data.pop("volumes") if "tags" in data: data.pop("tags") type = None if "type" in data: _type = data.pop("type") if isinstance(_type, dict) and "id" in _type: type = get_drink_type(_type.get("id")) if identifier == -1: drink = Drink() db.session.add(drink) else: drink = get_drink(identifier) if not drink: raise NotFound for key, value in data.items(): if hasattr(drink, key): setattr(drink, key, value if value != "" else None) if type: drink.type = type if volumes: set_volumes(volumes, drink) db.session.commit() return drink def set_volumes(volumes, drink): if isinstance(volumes, list): _volumes = [] for _volume in volumes: volume = set_volume(_volume) _volumes.append(volume) drink.volumes = _volumes def delete_drink(identifier): drink = get_drink(identifier) db.session.delete(drink) db.session.commit() def get_volume(identifier): return DrinkPriceVolume.query.get(identifier) def get_volumes(drink_id=None): if drink_id: return DrinkPriceVolume.query.filter(DrinkPriceVolume.drink_id == drink_id).all() return DrinkPriceVolume.query.all() def set_volume(data): allowed_keys = DrinkPriceVolume().serialize().keys() values = {key: value for key, value in data.items() if key in allowed_keys} prices = None ingredients = None if "prices" in values: prices = values.pop("prices") if "ingredients" in values: ingredients = values.pop("ingredients") id = None if "id" in values: id = values.pop("id") volume = None if id < 0: volume = DrinkPriceVolume(**values) db.session.add(volume) else: volume = get_volume(id) if not volume: raise NotFound for key, value in values.items(): setattr(volume, key, value if value != "" else None) if prices: set_prices(prices, volume) if ingredients: set_ingredients(ingredients, volume) return volume def set_prices(prices, volume): if isinstance(prices, list): _prices = [] for _price in prices: price = set_price(_price) _prices.append(price) volume.prices = _prices def set_ingredients(ingredients, volume): if isinstance(ingredients, list): _ingredietns = [] for _ingredient in ingredients: ingredient = set_ingredient(_ingredient) _ingredietns.append(ingredient) volume.ingredients = _ingredietns def delete_volume(identifier): volume = get_volume(identifier) db.session.delete(volume) db.session.commit() def get_price(identifier): if isinstance(identifier, int): return DrinkPrice.query.get(identifier) raise NotFound def get_prices(volume_id=None): if volume_id: return DrinkPrice.query.filter(DrinkPrice.volume_id_ == volume_id).all() return DrinkPrice.query.all() def set_price(data): allowed_keys = DrinkPrice().serialize().keys() values = {key: value for key, value in data.items() if key in allowed_keys} id = None if "id" in values: id = values.pop("id") price = None if id < 0: price = DrinkPrice(**values) db.session.add(price) else: price = get_price(id) if not price: raise NotFound for key, value in values.items(): setattr(price, key, value) return price def delete_price(identifier): price = get_price(identifier) db.session.delete(price) db.session.commit() def set_drink_ingredient(data): allowedKeys = DrinkIngredient().serialize().keys() drink = None values = {key: value for key, value in data.items() if key in allowedKeys} id = None if "id" in values: id = values.pop("id") if id < 0: drink_ingredient = DrinkIngredient(**values) db.session.add(drink_ingredient) else: drink_ingredient = DrinkIngredient.query.get(id) if not drink_ingredient: raise NotFound for key, value in values.items(): setattr(drink_ingredient, key, value if value != "" else None) return drink_ingredient def get_ingredient(identifier): return Ingredient.query.get(identifier) def set_ingredient(data): drink_ingredient_value = None extra_ingredient_value = None if "drink_ingredient" in data: drink_ingredient_value = data.pop("drink_ingredient") if "extra_ingredient" in data: extra_ingredient_value = data.pop("extra_ingredient") id = None if "id" in data: id = data.pop("id") ingredient = None if id < 0: ingredient = Ingredient(**data) db.session.add(ingredient) else: ingredient = get_ingredient(id) if not ingredient: raise NotFound if drink_ingredient_value: ingredient.drink_ingredient = set_drink_ingredient(drink_ingredient_value) if extra_ingredient_value: if "id" in extra_ingredient_value: ingredient.extra_ingredient = get_extra_ingredient(extra_ingredient_value.get("id")) return ingredient def delete_ingredient(identifier): ingredient = get_ingredient(identifier) if ingredient.drink_ingredient: db.session.delete(ingredient.drink_ingredient) db.session.delete(ingredient) db.session.commit() def get_extra_ingredients(): return ExtraIngredient.query.all() def get_extra_ingredient(identifier): return ExtraIngredient.query.get(identifier) def set_extra_ingredient(data): allowedKeys = ExtraIngredient().serialize().keys() if "id" in data: data.pop("id") values = {key: value for key, value in data.items() if key in allowedKeys} extra_ingredient = ExtraIngredient(**values) db.session.add(extra_ingredient) db.session.commit() return extra_ingredient def update_extra_ingredient(identifier, data): allowedKeys = ExtraIngredient().serialize().keys() if "id" in data: data.pop("id") values = {key: value for key, value in data.items() if key in allowedKeys} extra_ingredient = get_extra_ingredient(identifier) if extra_ingredient: for key, value in values.items(): setattr(extra_ingredient, key, value) db.session.commit() return extra_ingredient def delete_extra_ingredient(identifier): extra_ingredient = get_extra_ingredient(identifier) db.session.delete(extra_ingredient) db.session.commit() def save_drink_picture(identifier, file): drink = get_drink(identifier) if not drink.uuid: drink.uuid = str(uuid4()) db.session.commit() path = config["pricelist"]["path"] save_picture(file, f"{path}/{drink.uuid}") def get_drink_picture(identifier, size=None): drink = get_drink(identifier) if not drink.uuid: raise FileNotFoundError path = config["pricelist"]["path"] return get_picture(f"{path}/{drink.uuid}") def delete_drink_picture(identifier): drink = get_drink(identifier) if not drink.uuid: delete_picture(f"{config['pricelist']['path']}/{drink.uuid}") drink.uuid = None db.session.commit()