v0.1.30 - Throughput overview today-only mix cards; mix formula save 500 fix
Throughput Overview: Horse Mix and Grain Mix are now the first two cards and
show TODAY's output only. Removed the 7d/4w/6w/12w range selector; the cards
are fixed to Horse mix today, Grain mix today, Today, This week, 4-week average.
Mix Editor formula save: fix HTTP 500 on PUT /editor/mixes/{id}/formula. The
audit-diff path read the resolved formula by attribute, but the resolver returns
dicts -> AttributeError. Read by key and expire stale ORM state so the response
reflects the just-saved rows. Adds regression tests for both save branches.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,6 @@ from app.schemas.editor import (
|
||||
EditorProductRow,
|
||||
EditorProductUpdate,
|
||||
EditorResolvedMixFormula,
|
||||
EditorResolvedMixIngredient,
|
||||
)
|
||||
from app.services.change_log import (
|
||||
ENTITY_INGREDIENT,
|
||||
@@ -162,12 +161,16 @@ def _format_kg(value: float) -> str:
|
||||
|
||||
|
||||
def _formula_deltas(
|
||||
before: list[EditorResolvedMixIngredient] | list,
|
||||
after: list[EditorResolvedMixIngredient] | list,
|
||||
before: list[dict],
|
||||
after: list[dict],
|
||||
) -> list[dict]:
|
||||
"""Per-ingredient before/after deltas between two resolved formulas."""
|
||||
before_map = {row.raw_material_name: row.quantity_kg for row in before}
|
||||
after_map = {row.raw_material_name: row.quantity_kg for row in after}
|
||||
"""Per-ingredient before/after deltas between two resolved formulas.
|
||||
|
||||
`resolve_editor_mix_formula` returns plain dicts (ingredients are dicts too),
|
||||
so read the rows by key, not attribute.
|
||||
"""
|
||||
before_map = {row["raw_material_name"]: row["quantity_kg"] for row in before}
|
||||
after_map = {row["raw_material_name"]: row["quantity_kg"] for row in after}
|
||||
deltas: list[dict] = []
|
||||
for name in sorted(set(before_map) | set(after_map)):
|
||||
old = before_map.get(name)
|
||||
@@ -640,9 +643,12 @@ def replace_editor_mix_formula(
|
||||
)
|
||||
|
||||
db.flush()
|
||||
# Drop now-stale ORM state so the re-resolve reads the rows we just wrote
|
||||
# rather than the formerly-loaded ingredient collections from the identity map.
|
||||
db.expire_all()
|
||||
mix = _load_editor_mix_formula(db, mix_id=mix_id, tenant_id=tenant_id)
|
||||
after_formula = resolve_editor_mix_formula(db, tenant_id=tenant_id, mix=mix)
|
||||
deltas = _formula_deltas(before_formula.ingredients, after_formula.ingredients)
|
||||
deltas = _formula_deltas(before_formula["ingredients"], after_formula["ingredients"])
|
||||
if deltas:
|
||||
record_change(
|
||||
db,
|
||||
|
||||
Reference in New Issue
Block a user