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 import and_, or_, select
from sqlalchemy.orm import Session, contains_eager 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 ..core.security import get_current_active_user as get_user
from ..db.session import SessionFuture from ..db.session import SessionFuture
from ..models.menu_category import MenuCategory from ..models.menu_category import MenuCategory
@ -59,11 +64,8 @@ def get_update_product_prices_id(
def update_product_prices_list( def update_product_prices_list(
menu_category_id: uuid.UUID | None, date_: date, db: Session menu_category_id: uuid.UUID | None, date_: date, db: Session
) -> list[UpdateProductPricesItem]: ) -> list[UpdateProductPricesItem]:
list_ = ( product_version_onclause = and_(
select(ProductVersion) ProductVersion.product_id == Product.id,
.join(ProductVersion.menu_category)
.where(
and_(
or_( or_(
ProductVersion.valid_from == None, # noqa: E711 ProductVersion.valid_from == None, # noqa: E711
ProductVersion.valid_from <= date_, ProductVersion.valid_from <= date_,
@ -73,24 +75,55 @@ def update_product_prices_list(
ProductVersion.valid_till >= date_, ProductVersion.valid_till >= date_,
), ),
) )
) sku_version_onclause = and_(
) SkuVersion.sku_id == StockKeepingUnit.id,
if menu_category_id is not None: or_(SkuVersion.valid_from == None, SkuVersion.valid_from <= date_), # noqa: E711
list_ = list_.where(ProductVersion.menu_category_id == menu_category_id) or_(SkuVersion.valid_till == None, SkuVersion.valid_till >= date_), # noqa: E711
list_.order_by(
MenuCategory.sort_order,
MenuCategory.name,
ProductVersion.sort_order,
ProductVersion.name,
ProductVersion.valid_from.nullsfirst(),
).options(
contains_eager(ProductVersion.menu_category),
) )
return [ stmt = (
UpdateProductPricesItem(id=item.product_id, name=item.full_name, old_price=item.price, new_price=item.price) select(SkuVersion)
for item in db.execute(list_).scalars().all() .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) @router.post("", response_model=UpdateProductPrices)
@ -100,7 +133,7 @@ def save_update_product_prices(
) -> UpdateProductPrices: ) -> UpdateProductPrices:
with SessionFuture() as db: with SessionFuture() as db:
for item in data.items: 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() db.commit()
return UpdateProductPrices( return UpdateProductPrices(
date_=data.date_, date_=data.date_,
@ -116,7 +149,7 @@ def save_update_product_prices_id(
) -> UpdateProductPrices: ) -> UpdateProductPrices:
with SessionFuture() as db: with SessionFuture() as db:
for item in data.items: 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() db.commit()
return UpdateProductPrices( return UpdateProductPrices(
date_=data.date_, 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: def update_sku_price(sku_id: uuid.UUID, sale_price: Decimal, date_: date, db: Session) -> None:
raise NotImplementedError sv: SkuVersion = db.execute(
item: ProductVersion = db.execute( select(SkuVersion).where(
select(ProductVersion).where(
and_( and_(
ProductVersion.product_id == id_, SkuVersion.sku_id == sku_id,
or_( or_(SkuVersion.valid_from == None, SkuVersion.valid_from <= date_), # noqa: E711
ProductVersion.valid_from == None, # noqa: E711 or_(SkuVersion.valid_till == None, SkuVersion.valid_till >= date_), # noqa: E711
ProductVersion.valid_from <= date_,
),
or_(
ProductVersion.valid_till == None, # noqa: E711
ProductVersion.valid_till >= date_,
),
) )
) )
).scalar_one() ).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( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, 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 if sv.valid_from == date_:
db.commit() sv.sale_price = sale_price
else: # Create a new version of the product from the new details return
item.valid_till = date_ - timedelta(days=1)
product_version = ProductVersion( # Close current version the day before
product_id=item.product_id, sv.valid_till = date_ - timedelta(days=1)
name=item.name,
units=item.units, # Create a new version cloning everything else
menu_category_id=item.menu_category_id, new_sv = SkuVersion(
sale_category_id=item.sale_category_id, sku_id=sv.sku_id,
price=price, units=sv.units,
has_happy_hour=item.has_happy_hour, fraction=sv.fraction,
is_not_available=item.is_not_available, product_yield=sv.product_yield,
quantity=item.quantity, 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_from=date_,
valid_till=None, valid_till=None,
sort_order=item.sort_order,
) )
db.add(product_version) db.add(new_sv)