[pricelist] break api, new model

This commit is contained in:
Tim Gröger 2021-03-15 19:56:51 +01:00
parent 919a31bede
commit df1610557f
3 changed files with 140 additions and 106 deletions

View File

@ -124,4 +124,32 @@ def create_drink(current_session):
item in data for item in ["name", "ingredients"]
):
raise BadRequest("No correct Keys to create drink")
return jsonify(pricelist_controller.create_drink(data))
return "jsonify(pricelist_controller.create_drink(data))"
@pricelist_bp.route("/prices", methods=["GET"])
@pricelist_bp.route("/prices/<int:identifier>", methods=["GET"])
def get_prices(identifier=None):
if identifier:
result = pricelist_controller.get_price(identifier)
else:
result = pricelist_controller.get_prices()
return jsonify(result)
@pricelist_bp.route("/prices/volumes/<int:identifier>", methods=["POST"])
def create_price(identifier):
data = request.get_json()
return jsonify(pricelist_controller.set_price(identifier, data))
@pricelist_bp.route("/prices/<int:identifier>", methods=["PUT"])
def modify_price(identifier):
data = request.get_json()
return jsonify(pricelist_controller.update_price(identifier, data))
@pricelist_bp.route("/prices/<int:identifier>", methods=["DELETE"])
def delete_price(identifier):
pricelist_controller.delete_price(identifier)
return NO_CONTENT

View File

@ -43,28 +43,78 @@ class DrinkPrice(db.Model, ModelSerializeMixin):
__tablename__ = "drink_price"
id: int = db.Column("id", db.Integer, primary_key=True)
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False), nullable=False)
price: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
drink_id = db.Column("drink_id", db.Integer, db.ForeignKey("drink.id"))
drink = db.relationship("Drink", back_populates="prices")
no_auto: bool = db.Column(db.Boolean, default=False)
volume_id_ = db.Column("volume_id", db.Integer, db.ForeignKey("drink_price_volume.id"))
volume = db.relationship("DrinkPriceVolume", back_populates="prices")
public: bool = db.Column(db.Boolean, default=True)
description: Optional[str] = db.Column(db.String(30))
round_step: float = db.Column(db.Numeric(precision=3, scale=2, asdecimal=False), nullable=False, default=0.5)
class Ingredient(db.Model, ModelSerializeMixin):
class ExtraIngredient(db.Model, ModelSerializeMixin):
"""
Drink Build
ExtraIngredient
"""
__tablename__ = "extra_ingredient"
id: int = db.Column("id", db.Integer, primary_key=True)
name: str = db.Column(db.String(30), unique=True, nullable=False)
price: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
class DrinkIngredient(db.Model, ModelSerializeMixin):
"""
Drink Ingredient
"""
__tablename__ = "drink_ingredient"
id: int = db.Column("id", db.Integer, primary_key=True)
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False), nullable=False)
drink_parent_id: int = db.Column("drink_parent_id", db.Integer, db.ForeignKey("drink.id"))
drink_parent = db.relationship("Drink", foreign_keys=drink_parent_id)
drink_ingredient_id: int = db.Column("drink_ingredient_id", db.Integer, db.ForeignKey("drink.id"))
drink_ingredient: "Drink" = db.relationship("Drink", foreign_keys=drink_ingredient_id)
drink_ingredient: "Drink" = db.relationship("Drink")
price: float = 0
@property
def price(self):
return self.drink_ingredient.cost_price_pro_volume * self.volume
class Ingredient(db.Model, ModelSerializeMixin):
"""
Ingredient Associationtable
"""
__tablename__ = "ingredient_association"
id: int = db.Column("id", db.Integer, primary_key=True)
volume_id: int = db.Column(db.Integer, db.ForeignKey("drink_price_volume.id"))
drink_ingredient_id = db.Column(db.Integer, db.ForeignKey("drink_ingredient.id"))
drink_ingredient: DrinkIngredient = db.relationship(DrinkIngredient)
extra_ingredient_id = db.Column(db.Integer, db.ForeignKey("extra_ingredient.id"))
extra_ingredient: ExtraIngredient = db.relationship(ExtraIngredient)
class DrinkPriceVolume(db.Model, ModelSerializeMixin):
"""
Drink Volumes and Prices
"""
__tablename__ = "drink_price_volume"
id: int = db.Column("id", db.Integer, primary_key=True)
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
prices: [DrinkPrice] = db.relationship(DrinkPrice, back_populates="volume", cascade="all,delete,delete-orphan")
ingredients: [DrinkIngredient or ExtraIngredient] = []
_ingredients: [Ingredient] = db.relationship("Ingredient", foreign_keys=Ingredient.volume_id)
drink_id = db.Column(db.Integer, db.ForeignKey("drink.id"), nullable=False)
@property
def ingredients(self):
retVal = []
for ingredient in self._ingredients:
if ingredient.drink_ingredient_id != None:
retVal.append(ingredient.drink_ingredient)
if ingredient.extra_ingredient_id != None:
retVal.append(ingredient.extra_ingredient)
return retVal
class Drink(db.Model, ModelSerializeMixin):
@ -74,17 +124,15 @@ class Drink(db.Model, ModelSerializeMixin):
__tablename__ = "drink"
id: int = db.Column("id", db.Integer, primary_key=True)
article_id: Optional[str] = db.Column(db.String(64))
package_size: Optional[int] = db.Column(db.Integer)
name: str = db.Column(db.String(60), nullable=False)
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
cost_price: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
discount: float = db.Column(db.Numeric(precision=3, scale=2, asdecimal=False), nullable=False)
extra_charge: Optional[float] = db.Column(db.Numeric(precision=3, scale=2, asdecimal=False), default=0)
prices: [DrinkPrice] = db.relationship(
"DrinkPrice", back_populates="drink", cascade="all,delete,delete-orphan", order_by=[DrinkPrice.volume]
)
ingredients: [Ingredient] = db.relationship(
"Ingredient", back_populates="drink_parent", foreign_keys=Ingredient.drink_parent_id
)
volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
cost_price_pro_volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
cost_price_package_netto: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
tags: [Optional[Tag]] = db.relationship("Tag", secondary=drink_tag_association, cascade="save-update, merge")
type_id_ = db.Column("type_id", db.Integer, db.ForeignKey("drink_type.id"))
type = db.relationship("DrinkType")
type: DrinkType = db.relationship("DrinkType")
volumes: [DrinkPriceVolume] = db.relationship(DrinkPriceVolume)

View File

@ -3,7 +3,7 @@ from sqlalchemy.exc import IntegrityError
from flaschengeist import logger
from flaschengeist.database import db
from .models import Drink, DrinkPrice, Ingredient, Tag, DrinkType
from .models import Drink, DrinkPrice, Ingredient, Tag, DrinkType, DrinkPriceVolume, DrinkIngredient, ExtraIngredient
from math import ceil
@ -103,56 +103,6 @@ def delete_drink_type(identifier):
raise BadRequest("DrinkType still in use")
def round_price(price, round_step):
return round(ceil(float(price) / round_step) * round_step * 100) / 100
def calc_prices(drink, prices):
retVal = []
if len(drink.ingredients) > 0:
return calc_price_by_ingredients(drink, prices)
allowed_keys = DrinkPrice().serialize().keys()
for price in prices:
values = {key: value for key, value in price.items() if key in allowed_keys}
if values.get("no_auto"):
retVal.append(DrinkPrice(**values))
else:
volume = float(values.pop("volume"))
if "price" in values:
values.pop("price")
_price = float(drink.cost_price) / float(drink.volume) * volume
_price += _price * float(drink.discount)
if drink.extra_charge:
_price += float(drink.extra_charge)
_price = round_price(_price, float(price.get("round_step")))
retVal.append(DrinkPrice(volume=volume, price=_price, **values))
return retVal
def calc_price_by_ingredients(drink, prices):
allowed_keys = DrinkPrice().serialize().keys()
retVal = []
for price in prices:
values = {key: value for key, value in price.items() if key in allowed_keys}
if values.get("no_auto"):
retVal.append(DrinkPrice(**values))
else:
volume = float(values.pop("volume"))
if "price" in values:
values.pop("price")
_price = 0
for ingredient in drink.ingredients:
_price = (
float(ingredient.drink_ingredient.cost_price)
/ float(ingredient.drink_ingredient.volume)
* float(ingredient.volume)
)
_price += _price * float(drink.discount) + float(drink.extra_charge)
_price = round_price(_price, price.get("round_step"))
retVal.append(DrinkPrice(volume=volume, price=_price, **values))
return retVal
def get_drinks(name=None):
if name:
return Drink.query.filter(Drink.name.contains(name)).all()
@ -161,49 +111,57 @@ def get_drinks(name=None):
def get_drink(identifier):
if isinstance(identifier, int):
retVal = Drink.query.get(identifier)
return Drink.query.get(identifier)
elif isinstance(identifier, str):
retVal = Drink.query.filter(Tag.name == identifier).one_or_none()
return Drink.query.filter(Tag.name == identifier).one_or_none()
else:
logger.debug("Invalid identifier type for Drink")
raise BadRequest
if not retVal:
raise NotFound
return retVal
def add_prices(drink, prices):
for price in prices:
drink.prices.append(price)
def get_volume(identifier):
return DrinkPriceVolume.query.get(identifier)
def add_ingredients(drink, ingredients):
for identifier, volume in ingredients:
ingredient = Ingredient(volume=volume, drink_ingredient=get_drink(identifier))
drink.ingredients.append(ingredient)
def get_price(identifier):
if isinstance(identifier, int):
return DrinkPrice.query.get(identifier)
raise NotFound
def create_drink(data):
allowed_keys = Drink().serialize().keys()
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(identifier, data):
allowed_keys = DrinkPrice().serialize().keys()
values = {key: value for key, value in data.items() if key in allowed_keys}
prices = values.pop("prices", [])
ingredients = values.pop("ingredients", [])
if "id" in values:
values.pop("id")
drink = Drink(**values)
add_ingredients(drink, ingredients)
drink.prices = calc_prices(drink, prices)
db.session.add(drink)
update()
return drink
price = DrinkPrice(**values)
volume = get_volume(identifier)
if not volume:
raise BadRequest
volume.prices.append(price)
db.session.add(price)
db.session.commit()
return price
def delete_drink(identifier):
drink = get_drink(identifier)
for price in drink.prices:
def update_price(identifier, data):
allowed_keys = DrinkPrice().serialize().keys()
if "id" in data:
data.pop("id")
values = {key: value for key, value in data.items() if key in allowed_keys}
price = get_price(identifier)
for key, value in values:
setattr(price, key, value)
db.session.commit()
return price
def delete_price(identifier):
price = get_price(identifier)
db.session.delete(price)
for ingredient in drink.ingredients:
db.session.delete(ingredient)
db.session.delete(drink)
update()
db.session.commit()