Commit Graph

3 Commits

Author SHA1 Message Date
Craig a8aed9a84f TICKET-007 (backend): meals — from-log, unpack, components, recursive nutrition, cycle detection 2026-07-26 17:27:15 +01:00
Craig 32461b7405 TICKET-006 (backend): OFF normalization, scan/search/refresh, restore-on-rescan
- services/off.py: single normalizer module (kcal/kJ fallback, not-found
  rule); fetch_product/search_off degrade gracefully on upstream errors
  (503/timeout → None / []), never 500; User-Agent + timeouts on all calls
- routers/off.py: thin routes for GET /api/off/product/{barcode},
  GET /api/off/search, POST /api/off/refresh/{food_id} (404 unknown id,
  400 no-barcode)
- services/foods.py: restore-on-rescan (§3.1) — barcode collision on a
  soft-deleted food clears deleted_at + updates row instead of 409;
  GET /api/foods/recent ordered by most-recent daily_log appearance,
  deduped, soft-deleted excluded
- tests: httpx mocked at the boundary (MockTransport, no real OFF);
  48 new tests (normalizer unit + router + restore + recent + error paths)
- 152 passing (was 104)
2026-07-26 15:46:24 +01:00
Craig 3f2c765c84 TICKET-001: Foods CRUD with soft-delete
- POST/GET/PUT/DELETE /api/foods per spec 3.1 (minus restore)
- Service layer (services/foods.py) with shared soft-delete query helper
- FoodCreate extended, FoodUpdate/FoodRead schemas added
- Barcode conflict returns 409; deleted foods hidden from search,
  visible by id and via include_deleted=true
- 29 new tests, full suite green (36 passed)
2026-07-26 12:56:59 +01:00