[pricelist] break api, new model
This commit is contained in:
parent
919a31bede
commit
df1610557f
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
raise NotFound
|
||||
|
||||
|
||||
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:
|
||||
db.session.delete(price)
|
||||
for ingredient in drink.ingredients:
|
||||
db.session.delete(ingredient)
|
||||
db.session.delete(drink)
|
||||
update()
|
||||
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)
|
||||
db.session.commit()
|
||||
|
|
Loading…
Reference in New Issue