fix: bilancia ricette attende ≥5g di variazione; sale spurio in Bring!

- Recipe use modal: reset _scaleLastConfirmedGrams al peso attuale prima
  di aprire il modale, così la tara ha tempo; soglia ridotta 10→5g
- PHP useFromInventory: prima di auto-aggiungere a Bring! un prodotto esaurito,
  controlla se la famiglia shopping_name ha scorte da altri prodotti (es.
  'Sale marino iodato' esaurito ma 3kg di altri sali in dispensa → non aggiunge)
  JS, così il cron bringCleanupObsolete può auto-rimuovere
- Rimosso manualmente 'Sale' da Bring! (aggiunto senza marker dalla vecchia logica)
This commit is contained in:
dadaloop82
2026-05-10 15:45:56 +00:00
parent d1139a7e4b
commit 763b7fd057
3 changed files with 40 additions and 8 deletions
+24 -2
View File
@@ -1374,6 +1374,26 @@ function useFromInventory(PDO $db): void {
$product = $stmt->fetch();
if ($product) {
// Before adding to Bring!, check if the shopping_name family already
// has adequate stock from OTHER products (e.g. "Sale marino iodato" depleted
// but "Sale alimentare" has 1kg → no need to add to shopping list).
$sNameKey = strtolower(trim($product['shopping_name'] ?? ''));
$familyCoverage = 0;
if ($sNameKey !== '') {
$covStmt = $db->prepare("
SELECT SUM(i.quantity)
FROM inventory i
JOIN products p ON i.product_id = p.id
WHERE LOWER(TRIM(p.shopping_name)) = ? AND i.product_id != ? AND i.quantity > 0
");
$covStmt->execute([$sNameKey, $productId]);
$familyCoverage = (float)($covStmt->fetchColumn() ?: 0);
}
if ($familyCoverage > 0) {
// Family has stock — no need to restock, suppress Bring! add.
// Set addedToBring=true so the JS fallback is also suppressed.
$addedToBring = true;
} else {
try {
$auth = bringAuth();
if ($auth) {
@@ -1399,9 +1419,10 @@ function useFromInventory(PDO $db): void {
$addedToBring = false;
} else {
// Specification: specific product name (and brand) so the user knows which variant
// Add 🛒 marker so the cron cleanup can auto-remove if no longer needed.
$spec = $genericName !== $product['name']
? $product['name'] . ($product['brand'] ? ' · ' . $product['brand'] : '')
: ($product['brand'] ?: $product['name']);
? $product['name'] . ($product['brand'] ? ' · ' . $product['brand'] : '') . ' · 🛒 Esaurito'
: ($product['brand'] ?: $product['name']) . ' · 🛒 Esaurito';
$body = http_build_query([
'uuid' => $listUUID,
'purchase' => $bringName,
@@ -1420,6 +1441,7 @@ function useFromInventory(PDO $db): void {
} catch (Exception $e) {
// Silently fail — don't block inventory operation
}
} // end else (family not covered)
}
}
}
+15 -5
View File
@@ -624,8 +624,9 @@ function _scaleAutoFillRecipeUse(msg) {
return;
}
// Reject if weight hasn't changed enough from last confirmed reading
if (_scaleLastConfirmedGrams !== null && Math.abs(grams - _scaleLastConfirmedGrams) < 10) {
// Reject if weight hasn't changed enough from last confirmed reading.
// Threshold: 5g — gives enough time to tare after opening the modal.
if (_scaleLastConfirmedGrams !== null && Math.abs(grams - _scaleLastConfirmedGrams) < 5) {
return;
}
@@ -7651,8 +7652,8 @@ function showLowStockBringPrompt(result, afterCallback) {
// configured, or product already on list), silently attempt it from JS.
if (!result.added_to_bring && shoppingName) {
// Fire-and-forget — don't block the callback
// Use generic shopping name; specific name goes into specification.
const spec = shoppingName !== name ? name + (result.product_brand ? ` · ${result.product_brand}` : '') : '';
// Use generic shopping name; specific name + 🛒 marker in spec so cron cleanup can auto-remove.
const spec = (shoppingName !== name ? name + (result.product_brand ? ` · ${result.product_brand}` : '') : name) + ' · 🛒 Esaurito';
(async () => {
try {
const payload = { items: [{ name: shoppingName, specification: spec }] };
@@ -11150,7 +11151,16 @@ async function useRecipeIngredient(idx, productId, location, qtyNumber, btn, rec
_recipeUseContext = { idx, productId, btn, qtyNumber, recipeQty };
_recipeUseConfMode = null;
// Reset scale state: set the current weight as baseline so only a *change*
// of ≥5g after the modal opens triggers auto-fill (allows time to tare).
_cancelScaleAutoConfirm(false);
_scaleRecipeAutoFillPaused = false;
if (_scaleLatestWeight) {
const _baseline = _scaleToGrams(parseFloat(_scaleLatestWeight.value), _scaleLatestWeight.unit);
if (_baseline !== null && _baseline >= 5) _scaleLastConfirmedGrams = _baseline;
}
// Fetch inventory to build the modal
try {
const data = await api('inventory_list');
+1 -1
View File
@@ -1462,6 +1462,6 @@
</div>
</div>
<script src="assets/js/app.js?v=20260510j"></script>
<script src="assets/js/app.js?v=20260510k"></script>
</body>
</html>