fix: falso alert burro; JSON traduzioni corrotte; allineamento inventario

- Smart shopping: aggiungi family-coverage check per prodotti 'quasi finiti'.
  Se il shopping_name family ha scorte da altri prodotti (es. Burro conf)
  con unità diff (g/ml vs conf), l'alert 'sta finendo' viene soppresso.
- Corretto bug traduzioni: sezione 'action' duplicata in de/en/it.json
  causava JSONDecodeError in CI/CD (line 944 column 2).
- DB: allineamento inventario burro — rimossi 30g residui (usati),
  pulito opened_at da pacco nuovo Burro conf (comprato 2026-05-08).
This commit is contained in:
dadaloop82
2026-05-10 15:34:29 +00:00
parent 5fccb5309c
commit d1139a7e4b
6 changed files with 34 additions and 6 deletions
+7
View File
@@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- **Trasferisci a Ricette dalla chat** — Quando la chat con Gemini Chef genera una ricetta, compare il bottone "📥 Trasferisci a Ricette". Premendolo, Gemini converte il testo in JSON strutturato completo (titolo, pasti, ingredienti, passi), il backend arricchisce ogni ingrediente con product_id e location via fuzzy-match (identico a generateRecipe), la ricetta viene salvata in archivio e si apre direttamente nella sezione Ricette con tutti i pulsanti "Usa" e la modalità cottura completa.
- **Bottone "Apri la ricetta"** — Dopo un trasferimento riuscito, il bottone "📥 Trasferisci a Ricette" si trasforma direttamente in "📖 Apri la ricetta" (stesso elemento DOM), evitando problemi di sovrapposizione.
- **Crea una ricetta per ingrediente** — Nel pannello azione di ogni alimento in inventario compare il bottone "👨‍🍳 Crea una ricetta con questo" (teal, larghezza piena). Premendolo, Gemini genera una ricetta italiana usando quell'alimento come protagonista (stesso pipeline di chatToRecipe: arricchimento fuzzy-match inventario, meal=null, 8192 token max).
- **meal non auto-categorizzato** — Le ricette generate da chat o da ingrediente non vengono più auto-categorizzate (meal rimane null); il tag pasto nell'UI viene mostrato solo se valorizzato.
### Fixed
- **Smart shopping: falso positivo "quasi finito"** — Se un prodotto in grammi/ml era quasi esaurito (es. Burro 30g = 12%) ma lo stesso prodotto era disponibile anche come confezione (Burro 1 conf = 99%), il sistema segnalava ugualmente "sta finendo". Ora verifica se la famiglia `shopping_name` ha scorte da altri prodotti: se sì, l'alert viene soppresso. (Esempio: 30g di Burro + 1 conf di Burro → nessun alert.)
- **Traduzioni JSON corrotte** — La sezione `action` era duplicata nei file `de.json`, `en.json` e `it.json`, causando errori di parsing che bloccavano la CI/CD. Rimossa la sezione spuria.
## [1.7.7] - 2026-05-10
+13 -3
View File
@@ -6075,12 +6075,22 @@ function smartShopping(PDO $db): void {
}
}
// Almost finished — only flag if usage frequency justifies it
if ($qty > 0 && $pctLeft <= 15 && $isRegular) {
// Almost finished — only flag if usage frequency justifies it.
// Suppress if the same shopping_name family has adequate stock from OTHER products
// (e.g. "Burro g" at 12% but "Burro conf" at 99% → no need to flag).
$sNameLow = strtolower(trim($p['shopping_name'] ?? ''));
$familyOtherStock = ($sNameLow !== '') ? max(0, ($stockByShoppingName[$sNameLow] ?? 0) - $qty) : 0;
// For g/ml/kg/l: any conf/pz family stock ≥ 0.5 means a package is available.
// For conf/pz: needs at least 1 full unit from other family products.
$familyCovered = $sNameLow !== '' && $qty > 0 && (
(!in_array($unit, ['conf', 'pz']) && $familyOtherStock >= 0.5) ||
(in_array($unit, ['conf', 'pz']) && $familyOtherStock >= 1.0)
);
if (!$familyCovered && $qty > 0 && $pctLeft <= 15 && $isRegular) {
$urgency = $isFrequent ? 'high' : 'medium';
$reasons[] = 'Quasi finito (' . round($pctLeft) . '%)';
$score += 80;
} elseif ($qty > 0 && $pctLeft <= 30 && $isRegular) {
} elseif (!$familyCovered && $qty > 0 && $pctLeft <= 30 && $isRegular) {
if ($dailyRate > 0 && $daysLeft <= 5 && $isFrequent) {
$urgency = 'high';
$reasons[] = 'Finisce tra ~' . round($daysLeft) . 'gg';
+14
View File
@@ -152,5 +152,19 @@
"name": "Pancetta Dolce",
"location": "frigo",
"ts": 1778419507
},
"9e4189bd3f8cb1121e7389967dd4f74c": {
"days": 180,
"source": "rule",
"name": "Farina di grano tenero tipo rossa",
"location": "dispensa",
"ts": 1778427005
},
"e3472dd051ed13ae18fc96bbebedc1ba": {
"days": 60,
"source": "rule",
"name": "Lievito di birra",
"location": "dispensa",
"ts": 1778427005
}
}
-1
View File
@@ -478,7 +478,6 @@
"transferred": "Zu Rezepten hinzugefügt!",
"open_recipe": "Rezept öffnen"
},
"action": {
"cooking": {
"close": "Schließen",
"tts_btn": "Vorlesen",
-1
View File
@@ -478,7 +478,6 @@
"transferred": "Added to Recipes!",
"open_recipe": "Open recipe"
},
"action": {
"cooking": {
"close": "Close",
"tts_btn": "Read aloud",
-1
View File
@@ -478,7 +478,6 @@
"transferred": "Aggiunta alle Ricette!",
"open_recipe": "Apri la ricetta"
},
"action": {
"cooking": {
"close": "Chiudi",
"tts_btn": "Leggi ad alta voce",