v0.1.32 - Mix Calculator search, ingredient categories, throughput tidy-up

- Mix Calculator: searchable Mix Name picker (mirrors Throughput search)
- Ingredients Editor: add manual Category column; used to order Mix Calculator output
- Mix Calculator: surface formula-only mixes (no product yet) via -mix_id sentinel
- Throughput: remove unused For order / For stock destination controls from composer
- Editor change history: show timestamps in local time (stored UTC) instead of raw UTC

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 11:09:43 +12:00
co-authored by Claude Opus 4.8
parent 10722a65a6
commit 696f1e7b09
18 changed files with 628 additions and 112 deletions
+5
View File
@@ -838,6 +838,7 @@ def _serialize_ingredient(material: RawMaterial, usage_count: int) -> dict:
"kg_per_unit": material.kg_per_unit,
"status": material.status,
"rounding_decimals": material.rounding_decimals,
"category": material.category,
"notes": material.notes,
"cost_per_kg": cost_per_kg,
"usage_count": usage_count,
@@ -885,6 +886,7 @@ def create_editor_ingredient(
kg_per_unit=payload.kg_per_unit,
status=payload.status.strip() or "active",
rounding_decimals=payload.rounding_decimals,
category=(payload.category or "").strip() or None,
notes=payload.notes,
)
db.add(material)
@@ -928,6 +930,8 @@ def update_editor_ingredient(
updates["supplier"] = (updates["supplier"] or "").strip() or None
if "unit_of_measure" in updates and updates["unit_of_measure"] is not None:
updates["unit_of_measure"] = updates["unit_of_measure"].strip()
if "category" in updates:
updates["category"] = (updates["category"] or "").strip() or None
before = {field: getattr(material, field) for field in updates}
for field, value in updates.items():
setattr(material, field, value)
@@ -941,6 +945,7 @@ def update_editor_ingredient(
"kg_per_unit": "Kg per unit",
"status": "Status",
"rounding_decimals": "Rounding (dp)",
"category": "Category",
"notes": "Notes",
},
)