Fix: Recipe was crashing the whole thing
This commit is contained in:
55
brewman/alembic/versions/0e6c5953a63f_recipe.py
Normal file
55
brewman/alembic/versions/0e6c5953a63f_recipe.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"""recipe
|
||||||
|
|
||||||
|
Revision ID: 0e6c5953a63f
|
||||||
|
Revises: c39eb451a683
|
||||||
|
Create Date: 2021-11-01 12:11:16.813756
|
||||||
|
|
||||||
|
"""
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
from sqlalchemy import column, func, table, text
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "0e6c5953a63f"
|
||||||
|
down_revision = "c39eb451a683"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column("recipes", "product_id", new_column_name="sku_id")
|
||||||
|
op.alter_column("recipes", "valid_to", new_column_name="valid_till", existing_type=sa.DATE(), nullable=True)
|
||||||
|
op.alter_column("recipes", "valid_from", existing_type=sa.DATE(), nullable=True)
|
||||||
|
op.drop_constraint("recipes_product_id_fkey", "recipes", type_="foreignkey")
|
||||||
|
op.create_foreign_key(
|
||||||
|
op.f("fk_recipes_sku_id_stock_keeping_units"), "recipes", "stock_keeping_units", ["sku_id"], ["id"]
|
||||||
|
)
|
||||||
|
op.drop_column("recipes", "effective_to")
|
||||||
|
op.drop_column("recipes", "effective_from")
|
||||||
|
|
||||||
|
recipe = table(
|
||||||
|
"recipes",
|
||||||
|
column("sku_id", postgresql.UUID(as_uuid=True)),
|
||||||
|
column("valid_from", sa.Date()),
|
||||||
|
column("valid_till", sa.Date()),
|
||||||
|
)
|
||||||
|
|
||||||
|
op.create_exclude_constraint(
|
||||||
|
"uq_recipes_sku_id",
|
||||||
|
"recipes",
|
||||||
|
(recipe.c.sku_id, "="),
|
||||||
|
(func.daterange(recipe.c.valid_from, recipe.c.valid_till, text("'[]'")), "&&"),
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
# delete from recipe_items where recipe_id in (select id from recipes where product_id in (select product_id from recipes group by product_id having count(*) > 1) and effective_to is not null);
|
||||||
|
# delete from recipes where id in (select id from recipes where product_id in (select product_id from recipes group by product_id having count(*) > 1) and effective_to is not null);
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
pass
|
||||||
@ -1,7 +1,5 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import date
|
|
||||||
|
|
||||||
from sqlalchemy import Column, Date, ForeignKey, Numeric, Unicode
|
from sqlalchemy import Column, Date, ForeignKey, Numeric, Unicode
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
@ -13,7 +11,7 @@ class Recipe(Base):
|
|||||||
__tablename__ = "recipes"
|
__tablename__ = "recipes"
|
||||||
|
|
||||||
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||||
product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False)
|
sku_id = Column("sku_id", UUID(as_uuid=True), ForeignKey("stock_keeping_units.id"), nullable=False)
|
||||||
|
|
||||||
quantity = Column("quantity", Numeric(precision=15, scale=2), nullable=False)
|
quantity = Column("quantity", Numeric(precision=15, scale=2), nullable=False)
|
||||||
cost_price = Column("cost_price", Numeric(precision=15, scale=2), nullable=False)
|
cost_price = Column("cost_price", Numeric(precision=15, scale=2), nullable=False)
|
||||||
@ -23,31 +21,25 @@ class Recipe(Base):
|
|||||||
valid_from = Column("valid_from", Date, nullable=True)
|
valid_from = Column("valid_from", Date, nullable=True)
|
||||||
valid_till = Column("valid_till", Date, nullable=True)
|
valid_till = Column("valid_till", Date, nullable=True)
|
||||||
|
|
||||||
effective_from = Column("effective_from", Date, nullable=False)
|
items = relationship("RecipeItem", back_populates="recipe")
|
||||||
effective_to = Column("effective_to", Date)
|
sku = relationship("StockKeepingUnit", back_populates="recipes")
|
||||||
|
|
||||||
recipe_items = relationship("RecipeItem", backref="recipe")
|
|
||||||
product = relationship("Product", back_populates="recipes")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
product_id=None,
|
sku_id=None,
|
||||||
quantity=None,
|
quantity=None,
|
||||||
cost_price=None,
|
cost_price=None,
|
||||||
sale_price=None,
|
sale_price=None,
|
||||||
valid_from=None,
|
valid_from=None,
|
||||||
valid_till=None,
|
valid_till=None,
|
||||||
notes=None,
|
notes=None,
|
||||||
effective_from=None,
|
|
||||||
id_=None,
|
id_=None,
|
||||||
):
|
):
|
||||||
self.product_id = product_id
|
self.sku_id = sku_id
|
||||||
self.quantity = quantity
|
self.quantity = quantity
|
||||||
self.cost_price = cost_price
|
self.cost_price = cost_price
|
||||||
self.sale_price = sale_price
|
self.sale_price = sale_price
|
||||||
self.valid_from = valid_from
|
self.valid_from = valid_from
|
||||||
self.valid_till = valid_till
|
self.valid_till = valid_till
|
||||||
self.notes = "" if notes is None else notes
|
self.notes = "" if notes is None else notes
|
||||||
self.effective_from = date.today() if effective_from is None else effective_from
|
|
||||||
self.effective_to = None
|
|
||||||
self.id = id_
|
self.id = id_
|
||||||
|
|||||||
@ -17,11 +17,17 @@ class RecipeItem(Base):
|
|||||||
quantity = Column("quantity", Integer, nullable=False)
|
quantity = Column("quantity", Integer, nullable=False)
|
||||||
price = Column("price", Integer, nullable=False)
|
price = Column("price", Integer, nullable=False)
|
||||||
|
|
||||||
|
recipe = relationship("Recipe", back_populates="items")
|
||||||
product = relationship("Product")
|
product = relationship("Product")
|
||||||
|
|
||||||
def __init__(self, recipe_id=None, product_id=None, quantity=None, price=None, id_=None):
|
def __init__(self, recipe_id=None, product_id=None, quantity=None, price=None, recipe=None, id_=None):
|
||||||
self.recipe_id = recipe_id
|
self.recipe_id = recipe_id
|
||||||
self.product_id = product_id
|
self.product_id = product_id
|
||||||
self.quantity = quantity
|
self.quantity = quantity
|
||||||
self.price = price
|
self.price = price
|
||||||
|
if recipe is None:
|
||||||
|
self.recipe_id = recipe_id
|
||||||
|
else:
|
||||||
|
self.recipe_id = recipe.id
|
||||||
|
self.recipe = recipe
|
||||||
self.id = id_
|
self.id = id_
|
||||||
|
|||||||
@ -1,36 +1,14 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date, datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, validator
|
||||||
|
|
||||||
from . import to_camel
|
from . import to_camel
|
||||||
|
from .product import ProductLink
|
||||||
|
from .recipe_item import RecipeItem
|
||||||
class ProductLink(BaseModel):
|
|
||||||
id_: uuid.UUID = Field(...)
|
|
||||||
name: Optional[str]
|
|
||||||
units: Optional[str]
|
|
||||||
sale_price: Optional[Decimal]
|
|
||||||
is_sold: Optional[bool]
|
|
||||||
fraction_units: Optional[str]
|
|
||||||
fraction: Optional[Decimal]
|
|
||||||
product_yield: Optional[Decimal]
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
alias_generator = to_camel
|
|
||||||
|
|
||||||
|
|
||||||
class RecipeItem(BaseModel):
|
|
||||||
id_: Optional[uuid.UUID]
|
|
||||||
product: ProductLink
|
|
||||||
quantity: int
|
|
||||||
price: int
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
fields = {"id_": "id"}
|
|
||||||
|
|
||||||
|
|
||||||
class RecipeIn(BaseModel):
|
class RecipeIn(BaseModel):
|
||||||
@ -44,9 +22,6 @@ class RecipeIn(BaseModel):
|
|||||||
valid_from: Optional[date]
|
valid_from: Optional[date]
|
||||||
valid_till: Optional[date]
|
valid_till: Optional[date]
|
||||||
|
|
||||||
effective_from: Optional[date]
|
|
||||||
effective_till: Optional[date]
|
|
||||||
|
|
||||||
items: List[RecipeItem]
|
items: List[RecipeItem]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -54,6 +29,22 @@ class RecipeIn(BaseModel):
|
|||||||
alias_generator = to_camel
|
alias_generator = to_camel
|
||||||
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y") if v is not None else None}
|
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y") if v is not None else None}
|
||||||
|
|
||||||
|
@validator("valid_from", pre=True)
|
||||||
|
def parse_valid_from(cls, value):
|
||||||
|
if isinstance(value, date):
|
||||||
|
return value
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||||
|
|
||||||
|
@validator("valid_till", pre=True)
|
||||||
|
def parse_valid_till(cls, value):
|
||||||
|
if isinstance(value, date):
|
||||||
|
return value
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
return datetime.strptime(value, "%d-%b-%Y").date()
|
||||||
|
|
||||||
|
|
||||||
class Recipe(RecipeIn):
|
class Recipe(RecipeIn):
|
||||||
id_: uuid.UUID
|
id_: uuid.UUID
|
||||||
@ -65,8 +56,9 @@ class Recipe(RecipeIn):
|
|||||||
|
|
||||||
|
|
||||||
class RecipeBlank(RecipeIn):
|
class RecipeBlank(RecipeIn):
|
||||||
product: Optional[ProductLink]
|
product: Optional[ProductLink] # type: ignore[assignment]
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
anystr_strip_whitespace = True
|
anystr_strip_whitespace = True
|
||||||
alias_generator = to_camel
|
alias_generator = to_camel
|
||||||
|
json_encoders = {date: lambda v: v.strftime("%d-%b-%Y")}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
from brewman.schemas.product import ProductLink
|
from brewman.schemas.product import ProductLink
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class RecipeItem(BaseModel):
|
class RecipeItem(BaseModel):
|
||||||
@ -13,4 +13,4 @@ class RecipeItem(BaseModel):
|
|||||||
price: int
|
price: int
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
fields = {"id_": "id"}
|
fields = {"id_": "id"}
|
||||||
|
|||||||
Reference in New Issue
Block a user