feat: HA sensor enrichment, inventory edit guard, recipe ingredient fix, bread shelf-life

- HA sensor: expiring_list now includes full product details (location, brand,
  category, days_remaining, opened_at, vacuum_sealed, default_quantity, etc.)
- HA sensor: new expired_list attribute with full product details per expired item
- HA sensor: new low_stock_list attribute (items with quantity ≤ 1, full details)
- HA sensor: new sensor=product endpoint (?action=ha_sensor&sensor=product)
  with optional filters: &id=, &name=, &location=
- HA cron webhook: expiry alert items now carry full product details
- Inventory edit: confirm dialog when quantity exceeds unit-specific threshold
  (prevents data loss from unit-confusion typos, e.g. 183 conf instead of 0.183)
- Recipe AI: explicit rule against ingredient form substitution
  (fresh tomatoes ≠ passata, fresh milk ≠ UHT ≠ cream, etc.)
- Shelf-life: opened bread rules (piadina 2d, bauletto/pancarrè 4d, pane 3d)
- docs/wiki: HA page updated with new schema, examples, product endpoint

Closes #125
This commit is contained in:
dadaloop82
2026-05-29 05:40:25 +00:00
parent bc39361246
commit 1637cc1020
11 changed files with 476 additions and 56 deletions
+8
View File
@@ -464,6 +464,14 @@ function estimateOpenedExpiryDaysPHP(string $name, string $category, string $loc
if (preg_match('/\b(patata|patate|tubero)\b/', $n)) return 4;
if (preg_match('/\baglio\b/', $n)) return 14;
// ── F.extra: Bread in fridge (opened) ──────────────────────────────────
// Thin flatbreads (piadina, crescia, tigella) get mold very quickly
if (preg_match('/\b(piadina|piadelle?|crescia|tigella)\b/', $n)) return 2;
// Packaged sliced bread — preservatives help a bit
if (preg_match('/\b(bauletto|pancarrè|pan\s+carr|tramezzin)\b/', $n)) return 4;
// Generic bread / sandwich bread in fridge
if (preg_match('/\bpane\b/', $cat)) return 3;
// ── G: Fridge condiments — medium shelf-life ─────────────────────────
if (preg_match('/maionese|mayo|mayon/', $n)) return 90;
if (preg_match('/\bketchup\b/', $n)) return 90;