Added the funtionality to update product name and units when importing sales.
This commit is contained in:
@@ -16,7 +16,7 @@ from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "51013f52f0fb"
|
||||
down_revision = "9b4f7c2e81a3"
|
||||
down_revision = "c7e1a94b2d30"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
The mapping, once made, is standing truth: a Barker SKU whose mapping row exists is served
|
||||
from it verbatim, forever. The slugified product name is only the resolver for a Barker
|
||||
product never mapped before. Barker renames and units changes after first mapping are
|
||||
ignored — brewman master data is edited by hand when that matters.
|
||||
captured by creating a new product version or SKU version.
|
||||
|
||||
Resolution for one Barker line on business date ``date_``:
|
||||
|
||||
@@ -27,7 +27,7 @@ import re
|
||||
import uuid
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
from decimal import Decimal
|
||||
from typing import Any, Literal
|
||||
|
||||
@@ -87,6 +87,8 @@ def resolve_product(db: Session, line: BarkerSaleLine, date_: date) -> Provision
|
||||
"""
|
||||
binding = db.execute(select(BarkerProduct).where(BarkerProduct.barker_sku_id == line.sku_id)).scalar_one_or_none()
|
||||
if binding is not None:
|
||||
_update_name_if_needed(db, binding.brewman_product_id, line.name, date_)
|
||||
_update_units_if_needed(db, binding.brewman_sku_id, line.units, date_)
|
||||
return ProvisionedProduct(
|
||||
product_id=binding.brewman_product_id, sku_id=binding.brewman_sku_id, disposition="mapped"
|
||||
)
|
||||
@@ -100,7 +102,9 @@ def resolve_product(db: Session, line: BarkerSaleLine, date_: date) -> Provision
|
||||
.first()
|
||||
)
|
||||
if known_product_id is not None:
|
||||
_update_name_if_needed(db, known_product_id, line.name, date_)
|
||||
sku_id = _find_or_create_sku(db, known_product_id, line, date_)
|
||||
_update_units_if_needed(db, sku_id, line.units, date_)
|
||||
_write_mapping(db, line, known_product_id, sku_id)
|
||||
return ProvisionedProduct(product_id=known_product_id, sku_id=sku_id, disposition="linked")
|
||||
|
||||
@@ -109,7 +113,10 @@ def resolve_product(db: Session, line: BarkerSaleLine, date_: date) -> Provision
|
||||
if product_id is None:
|
||||
product_id = _create_product(db, line, date_)
|
||||
disposition = "created"
|
||||
else:
|
||||
_update_name_if_needed(db, product_id, line.name, date_)
|
||||
sku_id = _find_or_create_sku(db, product_id, line, date_)
|
||||
_update_units_if_needed(db, sku_id, line.units, date_)
|
||||
_write_mapping(db, line, product_id, sku_id)
|
||||
return ProvisionedProduct(product_id=product_id, sku_id=sku_id, disposition=disposition)
|
||||
|
||||
@@ -178,8 +185,7 @@ def _find_product_id_by_name(db: Session, name: str, date_: date) -> uuid.UUID |
|
||||
"""
|
||||
wanted = _normalize(name)
|
||||
normalized_name = _pg_normalize(ProductVersion.name)
|
||||
rows = (
|
||||
db.execute(
|
||||
rows = db.execute(
|
||||
select(ProductVersion.product_id, ProductVersion.name).where(
|
||||
normalized_name == wanted,
|
||||
(ProductVersion.valid_from == None) # noqa: E711
|
||||
@@ -187,15 +193,12 @@ def _find_product_id_by_name(db: Session, name: str, date_: date) -> uuid.UUID |
|
||||
(ProductVersion.valid_till == None) # noqa: E711
|
||||
| (ProductVersion.valid_till >= date_),
|
||||
)
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
if rows.count > 1:
|
||||
).all()
|
||||
if len(rows) > 1:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=f"Cannot import: '{name}' matches multiple products: "
|
||||
+ ", ".join(f"'{name}'" for (id_, name) in rows),
|
||||
+ ", ".join(f"'{p_name}'" for (id_, p_name) in rows),
|
||||
)
|
||||
return rows[0][0] if rows else None
|
||||
|
||||
@@ -323,3 +326,81 @@ def _write_mapping(db: Session, line: BarkerSaleLine, product_id: uuid.UUID, sku
|
||||
row.brewman_product_id = product_id
|
||||
row.brewman_sku_id = sku_id
|
||||
db.flush() # autoflush is off — later lookups must see this row
|
||||
|
||||
|
||||
def _update_name_if_needed(db: Session, product_id: uuid.UUID, new_name: str, date_: date) -> None:
|
||||
wanted = _normalize(new_name)
|
||||
active_pv = db.execute(
|
||||
select(ProductVersion).where(
|
||||
ProductVersion.product_id == product_id,
|
||||
(ProductVersion.valid_from == None) | (ProductVersion.valid_from <= date_), # noqa: E711
|
||||
(ProductVersion.valid_till == None) | (ProductVersion.valid_till >= date_), # noqa: E711
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
|
||||
if active_pv is not None and _normalize(active_pv.name) != wanted:
|
||||
if active_pv.valid_from == date_:
|
||||
active_pv.name = new_name
|
||||
active_pv.handle = ProductVersion.slugify(new_name)
|
||||
db.flush()
|
||||
else:
|
||||
active_pv.valid_till = date_ - timedelta(days=1)
|
||||
new_pv = ProductVersion(
|
||||
product_id=active_pv.product_id,
|
||||
name=new_name,
|
||||
description=active_pv.description,
|
||||
handle=ProductVersion.slugify(new_name),
|
||||
fraction_units=active_pv.fraction_units,
|
||||
product_group_id=active_pv.product_group_id,
|
||||
account_id=active_pv.account_id,
|
||||
is_purchased=active_pv.is_purchased,
|
||||
is_sold=active_pv.is_sold,
|
||||
allergen=active_pv.allergen,
|
||||
protein=active_pv.protein,
|
||||
carbohydrate=active_pv.carbohydrate,
|
||||
total_sugar=active_pv.total_sugar,
|
||||
added_sugar=active_pv.added_sugar,
|
||||
total_fat=active_pv.total_fat,
|
||||
saturated_fat=active_pv.saturated_fat,
|
||||
trans_fat=active_pv.trans_fat,
|
||||
cholestrol=active_pv.cholestrol,
|
||||
sodium=active_pv.sodium,
|
||||
msnf=active_pv.msnf,
|
||||
other_solids=active_pv.other_solids,
|
||||
total_solids=active_pv.total_solids,
|
||||
water=active_pv.water,
|
||||
valid_from=date_,
|
||||
valid_till=None,
|
||||
)
|
||||
db.add(new_pv)
|
||||
db.flush()
|
||||
|
||||
|
||||
def _update_units_if_needed(db: Session, sku_id: uuid.UUID, new_units: str, date_: date) -> None:
|
||||
wanted = _normalize(new_units)
|
||||
active_sv = db.execute(
|
||||
select(SkuVersion).where(
|
||||
SkuVersion.sku_id == sku_id,
|
||||
(SkuVersion.valid_from == None) | (SkuVersion.valid_from <= date_), # noqa: E711
|
||||
(SkuVersion.valid_till == None) | (SkuVersion.valid_till >= date_), # noqa: E711
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
|
||||
if active_sv is not None and _normalize(active_sv.units) != wanted:
|
||||
if active_sv.valid_from == date_:
|
||||
active_sv.units = new_units
|
||||
db.flush()
|
||||
else:
|
||||
active_sv.valid_till = date_ - timedelta(days=1)
|
||||
new_sv = SkuVersion(
|
||||
sku_id=active_sv.sku_id,
|
||||
units=new_units,
|
||||
fraction=active_sv.fraction,
|
||||
product_yield=active_sv.product_yield,
|
||||
cost_price=active_sv.cost_price,
|
||||
sale_price=active_sv.sale_price,
|
||||
valid_from=date_,
|
||||
valid_till=None,
|
||||
)
|
||||
db.add(new_sv)
|
||||
db.flush()
|
||||
|
||||
Reference in New Issue
Block a user