- Adds GET /api/products/{kind}/{id}/section?storeId=... exposing the
per-store memory the list page mirrors when a product is picked, so the
section dropdown reflects what the backend would auto-assign on POST.
- Treats backend warnings as errors via Directory.Build.props; fixes the
surfaced warnings (obsolete PostgreSqlBuilder ctor, nullable string[]
in IsEquivalentTo, redundant nullable flow).
- Annotates wire-exposed enums (ProductKind, UnitKind, UnitCategory,
UnitCategoryFlags) with JsonStringEnumConverter so they round-trip as
strings regardless of caller options. Unblocks the integration tests
that deserialize DTOs via GetFromJsonAsync without the global converter.
Mirrors the Phase 2 work on RecipeIngredient: ShoppingListItem grows
Quantity (decimal), UnitOfMeasureId / FamilyUnitOfMeasureId, IsApproximate,
and QuantityNote. The recipe-to-list copy now carries structured fields
verbatim instead of folding them into the free-form Name, and the
unit-in-use guard now also blocks deleting a family unit that's referenced
by a shopping list item.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2 of structured quantities + UoM. Replaces the free-form Quantity
string on RecipeIngredient with a structured (Quantity decimal, UnitOfMeasureId
or FamilyUnitOfMeasureId) pair, plus an IsApproximate + QuantityNote
escape hatch for "to taste" style entries. The unit FK pair mirrors the
existing Product / FamilyProduct pattern, with the same at-most-one and
tenant-scoping validation. Existing string Quantity values are dropped
per the agreed wipe-to-null migration plan.
Frontend ships a QuantityInput component (numeric field + unit dropdown
fed by a runes-cached effective catalog from /api/units) and a shared
formatter for read-only display. Recipe -> shopping list copy folds the
structured quantity into the item Name for now; Phase 3 will move the
fields onto ShoppingListItem directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1 of structured quantities + UoM. Introduces a global UnitOfMeasure
catalog (Code-keyed for stable backend lookup of canonical units like
"each") and FamilyUnitOfMeasure for family-scoped customs, mirroring the
product-catalog pattern. Endpoints expose the merged effective catalog
plus CRUD for family customs. Abbreviation uniqueness is enforced per
table at the DB layer and across tables at the API layer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>