flaschengeist/flaschengeist/plugins/pricelist/pricelist_controller.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

470 lines
14 KiB
Python
Raw Normal View History

from werkzeug.exceptions import BadRequest, NotFound
from sqlalchemy.exc import IntegrityError
2021-03-28 21:14:03 +00:00
from uuid import uuid4
from flaschengeist import logger
2021-03-22 22:17:44 +00:00
from flaschengeist.config import config
from flaschengeist.database import db
2021-03-29 19:28:48 +00:00
from flaschengeist.utils.picture import save_picture, get_picture, delete_picture
2021-04-14 20:42:57 +00:00
from flaschengeist.utils.decorators import extract_session
2021-03-28 21:14:03 +00:00
from .models import Drink, DrinkPrice, Ingredient, Tag, DrinkType, DrinkPriceVolume, DrinkIngredient, ExtraIngredient
2021-04-14 20:42:57 +00:00
from .permissions import EDIT_VOLUME, EDIT_PRICE, EDIT_INGREDIENTS_DRINK
def update():
db.session.commit()
def get_tags():
return Tag.query.all()
def get_tag(identifier):
if isinstance(identifier, int):
2021-03-28 21:14:03 +00:00
ret = Tag.query.get(identifier)
elif isinstance(identifier, str):
2021-03-28 21:14:03 +00:00
ret = Tag.query.filter(Tag.name == identifier).one_or_none()
else:
logger.debug("Invalid identifier type for Tag")
raise BadRequest
2021-03-28 21:14:03 +00:00
if ret is None:
raise NotFound
2021-03-28 21:14:03 +00:00
return ret
def create_tag(data):
try:
if "id" in data:
data.pop("id")
allowed_keys = Tag().serialize().keys()
values = {key: value for key, value in data.items() if key in allowed_keys}
tag = Tag(**values)
db.session.add(tag)
update()
return tag
except IntegrityError:
raise BadRequest("Name already exists")
def update_tag(identifier, data):
tag = get_tag(identifier)
allowed_keys = Tag().serialize().keys()
values = {key: value for key, value in data.items() if key in allowed_keys}
for key, value in values.items():
setattr(tag, key, value)
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):
2021-03-28 21:14:03 +00:00
ret = DrinkType.query.get(identifier)
elif isinstance(identifier, str):
2021-03-28 21:14:03 +00:00
ret = DrinkType.query.filter(Tag.name == identifier).one_or_none()
else:
logger.debug("Invalid identifier type for DrinkType")
raise BadRequest
2021-03-28 21:14:03 +00:00
if ret is None:
raise NotFound
2021-03-28 21:14:03 +00:00
return ret
def create_drink_type(name):
try:
2021-03-28 21:14:03 +00:00
drink_type = DrinkType(name=name)
db.session.add(drink_type)
update()
2021-03-28 21:14:03 +00:00
return drink_type
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):
2021-03-28 21:14:03 +00:00
drink_type = get_drink_type(identifier)
db.session.delete(drink_type)
try:
update()
except IntegrityError:
raise BadRequest("DrinkType still in use")
def _create_public_drink(drink):
_volumes = []
for volume in drink.volumes:
_prices = []
for price in volume.prices:
price: DrinkPrice
if price.public:
_prices.append(price)
volume.prices = _prices
if len(volume.prices) > 0:
_volumes.append(volume)
drink.volumes = _volumes
if len(drink.volumes) > 0:
return drink
return None
def get_drinks(name=None, public=False, limit=None, offset=None, search_name=None, search_key=None, ingredient=False):
count = None
if name:
query = Drink.query.filter(Drink.name.contains(name))
else:
query = Drink.query
if ingredient:
query = query.filter(Drink.cost_per_volume >= 0)
if search_name:
if search_key == "name":
query = query.filter(Drink.name.contains(search_name))
elif search_key == "article_id":
query = query.filter(Drink.article_id.contains(search_name))
elif search_key == "drink_type":
query = query.filter(Drink.type.has(DrinkType.name.contains(search_name)))
elif search_key == "tags":
query = query.filter(Drink.tags.any(Tag.name.contains(search_name)))
else:
query = query.filter(
(Drink.name.contains(search_name))
| (Drink.article_id.contains(search_name))
| (Drink.type.has(DrinkType.name.contains(search_name)))
| (Drink.tags.any(Tag.name.contains(search_name)))
)
if limit is not None:
count = query.count()
query = query.limit(limit)
if offset is not None:
query = query.offset(offset)
drinks = query.all()
if public:
return [_create_public_drink(drink) for drink in drinks if _create_public_drink(drink)], count
return drinks, count
def get_drink(identifier, public=False):
drink = None
if isinstance(identifier, int):
drink = Drink.query.get(identifier)
elif isinstance(identifier, str):
drink = Drink.query.filter(Tag.name == identifier).one_or_none()
else:
2021-03-28 21:14:03 +00:00
raise BadRequest("Invalid identifier type for Drink")
if drink is None:
raise NotFound
if public:
return _create_public_drink(drink)
2021-03-28 21:14:03 +00:00
return drink
def set_drink(data):
return update_drink(-1, data)
def update_drink(identifier, data):
2021-03-28 21:14:03 +00:00
try:
2021-04-14 20:42:57 +00:00
session = extract_session()
2021-03-28 21:14:03 +00:00
if "id" in data:
data.pop("id")
volumes = data.pop("volumes") if "volumes" in data else None
tags = []
2021-03-28 21:14:03 +00:00
if "tags" in data:
_tags = data.pop("tags")
if isinstance(_tags, list):
for _tag in _tags:
if isinstance(_tag, dict) and "id" in _tag:
tags.append(get_tag(_tag["id"]))
2021-03-28 21:14:03 +00:00
drink_type = data.pop("type")
if isinstance(drink_type, dict) and "id" in drink_type:
drink_type = drink_type["id"]
drink_type = get_drink_type(drink_type)
if identifier == -1:
drink = Drink()
db.session.add(drink)
else:
drink = get_drink(identifier)
for key, value in data.items():
if hasattr(drink, key):
setattr(drink, key, value if value != "" else None)
if drink_type:
drink.type = drink_type
2021-04-14 20:42:57 +00:00
if volumes is not None and session.user_.has_permission(EDIT_VOLUME):
drink.volumes = []
drink.volumes = set_volumes(volumes)
if len(tags) > 0:
drink.tags = tags
2021-03-28 21:14:03 +00:00
db.session.commit()
return drink
except (NotFound, KeyError):
raise BadRequest
def set_volumes(volumes):
retVal = []
2021-03-28 21:14:03 +00:00
if not isinstance(volumes, list):
raise BadRequest
for volume in volumes:
retVal.append(set_volume(volume))
return retVal
def delete_drink(identifier):
drink = get_drink(identifier)
if drink.uuid:
path = config["pricelist"]["path"]
delete_picture(f"{path}/{drink.uuid}")
db.session.delete(drink)
db.session.commit()
2021-03-15 18:56:51 +00:00
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):
2021-04-14 20:42:57 +00:00
session = extract_session()
allowed_keys = DrinkPriceVolume().serialize().keys()
values = {key: value for key, value in data.items() if key in allowed_keys}
prices = None
ingredients = None
2021-03-16 17:11:04 +00:00
if "prices" in values:
prices = values.pop("prices")
if "ingredients" in values:
ingredients = values.pop("ingredients")
2021-03-28 21:14:03 +00:00
vol_id = values.pop("id", None)
if vol_id < 0:
volume = DrinkPriceVolume(**values)
db.session.add(volume)
else:
2021-03-28 21:14:03 +00:00
volume = get_volume(vol_id)
if not volume:
raise NotFound
for key, value in values.items():
setattr(volume, key, value if value != "" else None)
2021-04-14 20:42:57 +00:00
if prices and session.user_.has_permission(EDIT_PRICE):
set_prices(prices, volume)
2021-04-14 20:42:57 +00:00
if ingredients and session.user_.has_permission(EDIT_INGREDIENTS_DRINK):
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()
2021-03-15 18:56:51 +00:00
def get_price(identifier):
if isinstance(identifier, int):
return DrinkPrice.query.get(identifier)
raise NotFound
2021-03-15 18:56:51 +00:00
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 = list(DrinkPrice().serialize().keys())
allowed_keys.append("description")
logger.debug(f"allowed_key {allowed_keys}")
values = {key: value for key, value in data.items() if key in allowed_keys}
2021-03-28 21:14:03 +00:00
price_id = values.pop("id", -1)
if price_id < 0:
price = DrinkPrice(**values)
db.session.add(price)
else:
2021-03-28 21:14:03 +00:00
price = get_price(price_id)
if not price:
raise NotFound
for key, value in values.items():
setattr(price, key, value)
2021-03-15 18:56:51 +00:00
return price
def delete_price(identifier):
price = get_price(identifier)
db.session.delete(price)
db.session.commit()
def set_drink_ingredient(data):
2021-03-28 21:14:03 +00:00
allowed_keys = DrinkIngredient().serialize().keys()
values = {key: value for key, value in data.items() if key in allowed_keys}
if "cost_per_volume" in values:
values.pop("cost_per_volume")
if "name" in values:
values.pop("name")
2021-03-28 21:14:03 +00:00
ingredient_id = values.pop("id", -1)
if ingredient_id < 0:
drink_ingredient = DrinkIngredient(**values)
db.session.add(drink_ingredient)
else:
2021-03-28 21:14:03 +00:00
drink_ingredient = DrinkIngredient.query.get(ingredient_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):
2021-03-18 16:26:02 +00:00
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")
2021-03-28 21:14:03 +00:00
ingredient_id = data.pop("id", -1)
if ingredient_id < 0:
ingredient = Ingredient(**data)
db.session.add(ingredient)
else:
2021-03-28 21:14:03 +00:00
ingredient = get_ingredient(ingredient_id)
if not ingredient:
raise NotFound
2021-03-18 16:26:02 +00:00
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):
2021-03-28 21:14:03 +00:00
allowed_keys = ExtraIngredient().serialize().keys()
if "id" in data:
data.pop("id")
2021-03-28 21:14:03 +00:00
values = {key: value for key, value in data.items() if key in allowed_keys}
extra_ingredient = ExtraIngredient(**values)
db.session.add(extra_ingredient)
db.session.commit()
return extra_ingredient
def update_extra_ingredient(identifier, data):
2021-03-28 21:14:03 +00:00
allowed_keys = ExtraIngredient().serialize().keys()
if "id" in data:
data.pop("id")
2021-03-28 21:14:03 +00:00
values = {key: value for key, value in data.items() if key in allowed_keys}
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()
2021-03-22 22:17:44 +00:00
def save_drink_picture(identifier, file):
drink = get_drink(identifier)
old_uuid = None
if drink.uuid:
old_uuid = drink.uuid
drink.uuid = str(uuid4())
db.session.commit()
2021-03-22 22:17:44 +00:00
path = config["pricelist"]["path"]
save_picture(file, f"{path}/{drink.uuid}")
if old_uuid:
delete_picture(f"{path}/{old_uuid}")
return drink
2021-03-22 22:17:44 +00:00
def get_drink_picture(identifier, size=None):
path = config["pricelist"]["path"]
drink = None
if isinstance(identifier, int):
drink = get_drink(identifier)
if isinstance(identifier, str):
drink = Drink.query.filter(Drink.uuid == identifier).one_or_none()
2021-04-14 18:03:44 +00:00
if drink:
return get_picture(f"{path}/{drink.uuid}", size)
raise FileNotFoundError
def delete_drink_picture(identifier):
drink = get_drink(identifier)
if drink.uuid:
delete_picture(f"{config['pricelist']['path']}/{drink.uuid}")
drink.uuid = None
db.session.commit()