Update product prices now working

This commit is contained in:
2026-01-26 14:00:14 +00:00
parent 2505ef7aec
commit 22f888500f

View File

@ -7,6 +7,11 @@ from fastapi import APIRouter, Depends, HTTPException, Security, status
from sqlalchemy import and_, or_, select
from sqlalchemy.orm import Session, contains_eager
from barker.models.product import Product
from barker.models.sale_category import SaleCategory
from barker.models.sku_version import SkuVersion
from barker.models.stock_keeping_unit import StockKeepingUnit
from ..core.security import get_current_active_user as get_user
from ..db.session import SessionFuture
from ..models.menu_category import MenuCategory
@ -59,38 +64,66 @@ def get_update_product_prices_id(
def update_product_prices_list(
menu_category_id: uuid.UUID | None, date_: date, db: Session
) -> list[UpdateProductPricesItem]:
list_ = (
select(ProductVersion)
.join(ProductVersion.menu_category)
.where(
and_(
or_(
ProductVersion.valid_from == None, # noqa: E711
ProductVersion.valid_from <= date_,
),
or_(
ProductVersion.valid_till == None, # noqa: E711
ProductVersion.valid_till >= date_,
),
)
)
product_version_onclause = and_(
ProductVersion.product_id == Product.id,
or_(
ProductVersion.valid_from == None, # noqa: E711
ProductVersion.valid_from <= date_,
),
or_(
ProductVersion.valid_till == None, # noqa: E711
ProductVersion.valid_till >= date_,
),
)
if menu_category_id is not None:
list_ = list_.where(ProductVersion.menu_category_id == menu_category_id)
list_.order_by(
MenuCategory.sort_order,
MenuCategory.name,
ProductVersion.sort_order,
ProductVersion.name,
ProductVersion.valid_from.nullsfirst(),
).options(
contains_eager(ProductVersion.menu_category),
sku_version_onclause = and_(
SkuVersion.sku_id == StockKeepingUnit.id,
or_(SkuVersion.valid_from == None, SkuVersion.valid_from <= date_), # noqa: E711
or_(SkuVersion.valid_till == None, SkuVersion.valid_till >= date_), # noqa: E711
)
return [
UpdateProductPricesItem(id=item.product_id, name=item.full_name, old_price=item.price, new_price=item.price)
for item in db.execute(list_).scalars().all()
]
stmt = (
select(SkuVersion)
.join(SkuVersion.menu_category)
.join(StockKeepingUnit, onclause=sku_version_onclause)
.join(StockKeepingUnit.product)
.join(ProductVersion, onclause=product_version_onclause)
.join(ProductVersion.sale_category)
)
if menu_category_id is not None:
stmt = stmt.where(SkuVersion.menu_category_id == menu_category_id)
stmt = stmt.order_by(
SaleCategory.name,
MenuCategory.sort_order,
MenuCategory.name,
Product.sort_order,
ProductVersion.name,
StockKeepingUnit.sort_order,
SkuVersion.units,
).options(
contains_eager(SkuVersion.menu_category),
contains_eager(SkuVersion.sku)
.contains_eager(StockKeepingUnit.product)
.contains_eager(Product.versions)
.contains_eager(ProductVersion.sale_category),
)
items = db.execute(stmt).unique().scalars().all()
# Build display name: "ProductName (units)" — similar to old full_name
out: list[UpdateProductPricesItem] = []
for sv in items:
full_name = f"{sv.sku.product.versions[0].name} ({sv.units})"
out.append(
UpdateProductPricesItem(
id=sv.sku_id,
name=full_name,
old_price=sv.sale_price,
new_price=sv.sale_price,
)
)
return out
@router.post("", response_model=UpdateProductPrices)
@ -100,7 +133,7 @@ def save_update_product_prices(
) -> UpdateProductPrices:
with SessionFuture() as db:
for item in data.items:
update_product(item.id, item.new_price, data.date_, db)
update_sku_price(item.id, item.new_price, data.date_, db)
db.commit()
return UpdateProductPrices(
date_=data.date_,
@ -116,7 +149,7 @@ def save_update_product_prices_id(
) -> UpdateProductPrices:
with SessionFuture() as db:
for item in data.items:
update_product(item.id, item.new_price, data.date_, db)
update_sku_price(item.id, item.new_price, data.date_, db)
db.commit()
return UpdateProductPrices(
date_=data.date_,
@ -125,46 +158,41 @@ def save_update_product_prices_id(
)
def update_product(id_: uuid.UUID, price: Decimal, date_: date, db: Session) -> None:
raise NotImplementedError
item: ProductVersion = db.execute(
select(ProductVersion).where(
def update_sku_price(sku_id: uuid.UUID, sale_price: Decimal, date_: date, db: Session) -> None:
sv: SkuVersion = db.execute(
select(SkuVersion).where(
and_(
ProductVersion.product_id == id_,
or_(
ProductVersion.valid_from == None, # noqa: E711
ProductVersion.valid_from <= date_,
),
or_(
ProductVersion.valid_till == None, # noqa: E711
ProductVersion.valid_till >= date_,
),
SkuVersion.sku_id == sku_id,
or_(SkuVersion.valid_from == None, SkuVersion.valid_from <= date_), # noqa: E711
or_(SkuVersion.valid_till == None, SkuVersion.valid_till >= date_), # noqa: E711
)
)
).scalar_one()
if item.valid_till is not None:
# Allow adding a product here splitting the valid from and to, but not implemented right now
if sv.valid_till is not None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Product has been invalidated",
detail="SKU version has been invalidated",
)
if item.valid_from == date_: # Update the product as valid from the the same
item.price = price
db.commit()
else: # Create a new version of the product from the new details
item.valid_till = date_ - timedelta(days=1)
product_version = ProductVersion(
product_id=item.product_id,
name=item.name,
units=item.units,
menu_category_id=item.menu_category_id,
sale_category_id=item.sale_category_id,
price=price,
has_happy_hour=item.has_happy_hour,
is_not_available=item.is_not_available,
quantity=item.quantity,
valid_from=date_,
valid_till=None,
sort_order=item.sort_order,
)
db.add(product_version)
if sv.valid_from == date_:
sv.sale_price = sale_price
return
# Close current version the day before
sv.valid_till = date_ - timedelta(days=1)
# Create a new version cloning everything else
new_sv = SkuVersion(
sku_id=sv.sku_id,
units=sv.units,
fraction=sv.fraction,
product_yield=sv.product_yield,
cost_price=sv.cost_price,
sale_price=sale_price,
has_happy_hour=sv.has_happy_hour,
menu_category_id=sv.menu_category_id,
valid_from=date_,
valid_till=None,
)
db.add(new_sv)