Remove interval% from annual waste info; fix conf whole-qty using package expiry not opened shelf-life

This commit is contained in:
dadaloop82
2026-04-29 17:05:38 +00:00
parent e71ef3aba3
commit 8d02e76501
5 changed files with 18 additions and 6 deletions
+14
View File
@@ -1672,6 +1672,19 @@ function getStats(PDO $db): void {
$originalExpiry = !empty($item['expiry_date']) ? strtotime($item['expiry_date']) : null;
if (!empty($item['opened_at'])) {
// For conf unit: if all whole packages (no fraction), the opened_at tracks when the
// last package was first used, but the remaining whole confs are still sealed.
// Use the original package expiry, not the opened shelf-life.
if ($item['unit'] === 'conf' && $originalExpiry !== null) {
$qty = (float)$item['quantity'];
$frac = round($qty - (float)(int)floor($qty + 0.001), 4);
if ($frac < 0.001) {
// All whole: treat as sealed — use original expiry
$item['opened_expiry'] = $item['expiry_date'] ?? null;
$item['days_to_expiry'] = (int)round(($originalExpiry - $today) / 86400);
goto after_expiry;
}
}
// Compute opened shelf-life using AI (with rule-based fallback + persistent cache).
// The vacuum-sealed multiplier is already handled inside getOpenedShelfLifeDays.
$openedDays = getOpenedShelfLifeDays($item['name'], $item['category'], $item['location'], (bool)$vacuum);
@@ -1683,6 +1696,7 @@ function getStats(PDO $db): void {
$item['opened_expiry'] = date('Y-m-d', $finalExpiry);
$item['days_to_expiry'] = (int)round(($finalExpiry - $today) / 86400);
} else {
after_expiry:
// Legacy: no opened_at, use stored expiry_date as-is
$item['opened_expiry'] = $item['expiry_date'] ?? null;
$item['days_to_expiry'] = $originalExpiry !== null
+1 -3
View File
@@ -2293,9 +2293,7 @@ function _renderAntiWasteSection(used30, wasted30, usedP30, wastedP30, usedP60,
const avgAnnualKg = Math.round(bm.avgKgMonth * 12);
const annualInfo = t('antiwaste.annual_info')
.replace('{you}', myAnnualKg)
.replace('{avg}', avgAnnualKg)
.replace('{min}', bm.rangeMin)
.replace('{max}', bm.rangeMax);
.replace('{avg}', avgAnnualKg);
// Build all badge objects (shown 4 at a time, rotated every 5 min)
const diffPct = avgRate - myRate;
+1 -1
View File
@@ -700,7 +700,7 @@
"live_on": "Live-Daten",
"live_off": "Offline",
"meals": "Mahlzeiten",
"annual_info": "📅 Du ~{you} kg/Jahr · Ø ~{avg} kg/Jahr · Spanne {min}{max}%",
"annual_info": "📅 Du ~{you} kg/Jahr · Ø ~{avg} kg/Jahr",
"badge_rate": "Verlustquote",
"badge_saved_money": "gespart vs Ø",
"badge_wasted": "verloren",
+1 -1
View File
@@ -699,7 +699,7 @@
"live_on": "Live data",
"live_off": "Offline",
"meals": "meals",
"annual_info": "📅 You ~{you} kg/yr · avg ~{avg} kg/yr · range {min}{max}%",
"annual_info": "📅 You ~{you} kg/yr · avg ~{avg} kg/yr",
"badge_rate": "loss rate",
"badge_saved_money": "saved vs avg",
"badge_wasted": "items lost",
+1 -1
View File
@@ -699,7 +699,7 @@
"live_on": "Dati in tempo reale",
"live_off": "Offline",
"meals": "pasti",
"annual_info": "📅 Tu ~{you} kg/anno · media ~{avg} kg/anno · intervallo {min}{max}%",
"annual_info": "📅 Tu ~{you} kg/anno · media ~{avg} kg/anno",
"badge_rate": "tasso perdita",
"badge_saved_money": "risparmio vs media",
"badge_wasted": "prod. persi",