flaschengeist/flaschengeist/plugins/pricelist/models.py

180 lines
6.0 KiB
Python

from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
from flaschengeist.database import db
from flaschengeist.models import ModelSerializeMixin, Serial
from flaschengeist.models.image import Image
from typing import Optional
drink_tag_association = db.Table(
"drink_x_tag",
db.Column("drink_id", Serial, db.ForeignKey("drink.id")),
db.Column("tag_id", Serial, db.ForeignKey("drink_tag.id")),
)
drink_type_association = db.Table(
"drink_x_type",
db.Column("drink_id", Serial, db.ForeignKey("drink.id")),
db.Column("type_id", Serial, db.ForeignKey("drink_type.id")),
)
class Tag(db.Model, ModelSerializeMixin):
"""
Tag
"""
__tablename__ = "drink_tag"
id: int = db.Column("id", Serial, primary_key=True)
name: str = db.Column(db.String(30), nullable=False, unique=True)
color: str = db.Column(db.String(7), nullable=False)
class DrinkType(db.Model, ModelSerializeMixin):
"""
DrinkType
"""
__tablename__ = "drink_type"
id: int = db.Column("id", Serial, primary_key=True)
name: str = db.Column(db.String(30), nullable=False, unique=True)
class DrinkPrice(db.Model, ModelSerializeMixin):
"""
PriceFromVolume
"""
__tablename__ = "drink_price"
id: int = db.Column("id", Serial, primary_key=True)
price: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
volume_id_ = db.Column("volume_id", Serial, db.ForeignKey("drink_price_volume.id"))
volume: "DrinkPriceVolume" = None
_volume: "DrinkPriceVolume" = db.relationship("DrinkPriceVolume", back_populates="_prices", join_depth=1)
public: bool = db.Column(db.Boolean, default=True)
description: Optional[str] = db.Column(db.String(30))
def __repr__(self):
return f"DrinkPric({self.id},{self.price},{self.public},{self.description})"
class ExtraIngredient(db.Model, ModelSerializeMixin):
"""
ExtraIngredient
"""
__tablename__ = "drink_extra_ingredient"
id: int = db.Column("id", Serial, 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", Serial, primary_key=True)
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False), nullable=False)
ingredient_id: int = db.Column(Serial, db.ForeignKey("drink.id"))
cost_per_volume: float
name: str
_drink_ingredient: Drink = db.relationship("Drink")
@property
def cost_per_volume(self):
return self._drink_ingredient.cost_per_volume if self._drink_ingredient else None
@property
def name(self):
return self._drink_ingredient.name if self._drink_ingredient else None
class Ingredient(db.Model, ModelSerializeMixin):
"""
Ingredient Associationtable
"""
__tablename__ = "drink_ingredient_association"
id: int = db.Column("id", Serial, primary_key=True)
volume_id = db.Column(Serial, db.ForeignKey("drink_price_volume.id"))
drink_ingredient: Optional[DrinkIngredient] = db.relationship(DrinkIngredient, cascade="all,delete")
extra_ingredient: Optional[ExtraIngredient] = db.relationship(ExtraIngredient)
_drink_ingredient_id = db.Column(Serial, db.ForeignKey("drink_ingredient.id"))
_extra_ingredient_id = db.Column(Serial, db.ForeignKey("drink_extra_ingredient.id"))
class MinPrices(ModelSerializeMixin):
"""
MinPrices
"""
percentage: float
price: float
class DrinkPriceVolume(db.Model, ModelSerializeMixin):
"""
Drink Volumes and Prices
"""
__tablename__ = "drink_price_volume"
id: int = db.Column("id", Serial, primary_key=True)
drink_id = db.Column(Serial, db.ForeignKey("drink.id"))
drink: "Drink" = None
_drink: "Drink" = db.relationship("Drink", back_populates="_volumes")
volume: float = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
min_prices: list[MinPrices] = []
# ingredients: list[Ingredient] = []
prices: list[DrinkPrice] = []
_prices: list[DrinkPrice] = db.relationship(
DrinkPrice, back_populates="_volume", cascade="all,delete,delete-orphan"
)
ingredients: list[Ingredient] = db.relationship(
"Ingredient",
foreign_keys=Ingredient.volume_id,
cascade="all,delete,delete-orphan",
)
def __repr__(self):
return f"DrinkPriceVolume({self.id},{self.drink_id},{self.volume},{self.prices})"
class Drink(db.Model, ModelSerializeMixin):
"""
DrinkPrice
"""
__tablename__ = "drink"
id: int = db.Column("id", Serial, 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: Optional[float] = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
cost_per_volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
cost_per_package: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
has_image: bool = False
receipt: Optional[list[str]] = db.Column(db.PickleType(protocol=4))
_type_id = db.Column("type_id", Serial, db.ForeignKey("drink_type.id"))
_image_id = db.Column("image_id", Serial, db.ForeignKey("image.id"))
image_: Image = db.relationship("Image", cascade="all, delete", foreign_keys=[_image_id])
tags: Optional[list[Tag]] = db.relationship("Tag", secondary=drink_tag_association, cascade="save-update, merge")
type: Optional[DrinkType] = db.relationship("DrinkType", foreign_keys=[_type_id])
volumes: list[DrinkPriceVolume] = []
_volumes: list[DrinkPriceVolume] = db.relationship(
DrinkPriceVolume, back_populates="_drink", cascade="all,delete,delete-orphan"
)
def __repr__(self):
return f"Drink({self.id},{self.name},{self.volumes})"
@property
def has_image(self):
return self.image_ is not None