IPriceService (record/insight/history) wired into PurchaseService.
CompletePurchaseAsync, deriving a PriceObservation per resolved
PurchaseItem. Latest/average/median/lowest/unit-price all computed
in-memory (no MEDIAN in SQLite).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PriceObservation has zero mutation methods, enforced by a reflection
test. Fixed a real bug found while writing the EF config: Product ->
PriceObservation was wired Cascade (copy-paste), which would let
deleting a Product silently destroy its price history. Changed to
Restrict.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retailer/StoreLocation per AGENTS.md §5.5. DEC-011: store tracking is
optional everywhere (nullable FKs), so recording a purchase never
requires picking a store first.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Camera-based barcode scan page using the native BarcodeDetector API
(no bundler in this project, so no vendored scanning library) with a
manual-entry fallback for unsupported browsers. Adds the
/products/barcode/{barcode} and /api/products/barcode/{barcode}
routes ProductController was missing, plus an "Add to my list" action
on product details. Verified live against the real Open Food Facts
API end to end. "Record price" deferred to CW-EPIC-05, which doesn't
exist yet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
OpenFoodFactsProductDataProvider registered as a typed HttpClient,
giving CW-STORY-04.3's barcode flow a real provider. Response models
stay internal to Infrastructure; failures are caught narrowly and
logged via a source-generated LoggerMessage delegate.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
IProductDataProvider abstraction per AGENTS.md §9; ProductService.
ResolveBarcodeAsync does local-first lookup with provider fallback
and persists accepted results. No real provider registered yet
(CW-STORY-04.4) — flow is fully tested via a fake provider.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
IProductService/ProductService return display-ready DTOs (BrandName/
ConceptName resolved via join) rather than raw Product entities.
ProductController routes match AGENTS.md §11; price/insight fields
deferred until CW-EPIC-05 exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Brand, Product (aggregate root for ProductIdentifier), ProductIdentifier,
and HouseholdProductPreference, per AGENTS.md §5.2/5.3. Built ahead of
MVP-tagged epics per DEC-010 (explicit founder direction to work epics
in strict numeric order).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add toggle/skip/delete with optimistic concurrency handling and jQuery
progressive enhancement (CW-STORY-03.4), then a mobile-first touch-target
and quick-add polish pass (CW-STORY-03.5).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>