From f2e4c4d3c65a33b91d42a678232da0a492b9d631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=A4fliger?= Date: Wed, 5 Nov 2025 09:07:01 +0100 Subject: [PATCH] no message --- Abrechnung/module.php | 114 ++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/Abrechnung/module.php b/Abrechnung/module.php index 3e8ab31..858e616 100644 --- a/Abrechnung/module.php +++ b/Abrechnung/module.php @@ -293,7 +293,10 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) return ['row' => '', 'value' => 0]; } - // 1️⃣ Relevante Tarife für diese Verbrauchsart finden + // Zeitzone setzen, um strtotime()-Abweichungen zu vermeiden + date_default_timezone_set('Europe/Zurich'); + + // 1️⃣ Relevante Tarife nach Typ filtern $filteredTariffs = array_filter($tariffs, function ($t) use ($type) { return strtolower(trim($t['unit_type'] ?? '')) === strtolower(trim($type)); }); @@ -303,40 +306,53 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) return ['row' => '', 'value' => 0]; } - // 2️⃣ Zeitlich sortieren + // 2️⃣ Zeitstempel konvertieren und sortieren foreach ($filteredTariffs as &$t) { $t['start_ts'] = is_numeric($t['start']) ? intval($t['start']) : strtotime($t['start']); $t['end_ts'] = is_numeric($t['end']) ? intval($t['end']) : strtotime($t['end']); + + if (!$t['start_ts'] || !$t['end_ts']) { + IPS_LogMessage('Abrechnung', "⚠ Ungültiger Tarifzeitraum in Tarifdefinition: " . json_encode($t)); + } else { + IPS_LogMessage('Abrechnung', sprintf( + " 🕓 Tarif gültig von %s bis %s @ %.3f Rp", + date('d.m.Y H:i', $t['start_ts']), + date('d.m.Y H:i', $t['end_ts']), + floatval($t['price']) + )); + } } unset($t); + usort($filteredTariffs, fn($a, $b) => $a['start_ts'] <=> $b['start_ts']); - // 3️⃣ Startpunkt setzen + // 3️⃣ Abrechnungslogik starten $currentStart = $from; $segmentIndex = 1; - // Schleife bis Abrechnungsende while ($currentStart < $to) { + IPS_LogMessage('Abrechnung', "➡️ Segment {$segmentIndex} Startzeit: " . date('d.m.Y H:i', $currentStart)); - IPS_LogMessage('Abrechnung', "➡️ Segment $segmentIndex: Beginne bei " . date('d.m.Y H:i', $currentStart)); - - // 🔹 Nächsten geloggten Wert nach Startzeit holen - $startValue = $this->GetValueAt($varId, $currentStart, true); - if ($startValue === null) { - IPS_LogMessage('Abrechnung', "⚠ Kein Startwert gefunden bei " . date('d.m.Y H:i', $currentStart)); - break; - } - - // 🔹 Aktiven Tarif bestimmen + // Aktiven Tarif bestimmen $activeTariff = null; foreach ($filteredTariffs as $t) { - if ($t['start_ts'] <= $currentStart && $currentStart < $t['end_ts']) { + $startTs = intval($t['start_ts']); + $endTs = intval($t['end_ts']); + + if ($startTs === 0 || $endTs === 0) continue; + + if ($startTs <= $currentStart && $currentStart < $endTs) { $activeTariff = $t; + IPS_LogMessage('Abrechnung', sprintf( + " ✅ Aktiver Tarif gefunden: %.2f Rp (gültig %s → %s)", + floatval($t['price']), + date('d.m.Y H:i', $startTs), + date('d.m.Y H:i', $endTs) + )); break; } } - // 🔹 Falls kein Tarif aktiv → 0 Rp if (!$activeTariff) { IPS_LogMessage('Abrechnung', "⚠ Kein Tarif aktiv bei " . date('d.m.Y H:i', $currentStart) . " → 0 Rp"); $activeTariff = [ @@ -347,44 +363,37 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) ]; } - $tariffEnd = $activeTariff['end_ts']; + $tariffEnd = intval($activeTariff['end_ts']); $tariffPrice = floatval($activeTariff['price']); $tariffLabel = number_format($tariffPrice, 2, ',', ''); - IPS_LogMessage('Abrechnung', sprintf( - " 🧾 Aktiver Tarif: %.3f Rp (%s - %s)", - $tariffPrice, - date('d.m.Y H:i', $activeTariff['start_ts']), - date('d.m.Y H:i', $activeTariff['end_ts']) - )); - - // 🔹 Prüfen, ob Tarif vor Abrechnungsende endet - if ($tariffEnd < $to) { - // Tarif endet vor Rechnungsende → Segment bis Tarifende abrechnen - $segmentEnd = $tariffEnd; - } else { - // Tarif reicht bis oder über Rechnungsende → letztes Segment - $segmentEnd = $to; - } - - // 🔹 Nächsten Archivwert nach Segmentende lesen - $endValue = $this->GetValueAt($varId, $segmentEnd, true); - if ($endValue === null) { - IPS_LogMessage('Abrechnung', "⚠ Kein Endwert gefunden bei " . date('d.m.Y H:i', $segmentEnd)); + // Archivwerte abrufen + $startValue = $this->GetValueAt($varId, $currentStart, true); + if ($startValue === null) { + IPS_LogMessage('Abrechnung', "⚠ Kein Startwert für " . date('d.m.Y H:i', $currentStart)); break; } - // 🔹 Verbrauch und Kosten + // Wenn Tarif endet vor Rechnungsende → Segment bis Tarifende + $segmentEnd = ($tariffEnd < $to) ? $tariffEnd : $to; + + $endValue = $this->GetValueAt($varId, $segmentEnd, true); + if ($endValue === null) { + IPS_LogMessage('Abrechnung', "⚠ Kein Endwert für " . date('d.m.Y H:i', $segmentEnd)); + break; + } + + // Verbrauch und Kosten $verbrauch = max(0, $endValue - $startValue); $kosten = round(($tariffPrice / 100) * $verbrauch, 2); $totalCost += $kosten; IPS_LogMessage('Abrechnung', sprintf( - " 📊 Segment %d: Start=%.3f, Ende=%.3f, Verbrauch=%.3f, Tarif=%.3f Rp → %.2f CHF", + " 📊 Segment %d: %.3f → %.3f (Δ=%.3f) | Tarif=%.3f Rp | Kosten=%.2f CHF", $segmentIndex, $startValue, $endValue, $verbrauch, $tariffPrice, $kosten )); - // 🔹 Zeile erzeugen + // Tabellenzeile $rows .= " {$meter['name']} @@ -398,16 +407,35 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) " . number_format($kosten, 2) . " "; - // 🔹 Falls Tarif endet → nächster Zyklus startet am Ende des Tarifs + // Neuer Startpunkt = Ende des aktuellen Tarifs if ($tariffEnd < $to) { - $currentStart = $tariffEnd; + $currentStart = $tariffEnd; // ⬅ kein +1! } else { - break; // Letztes Segment erreicht + break; } $segmentIndex++; } + if ($rows === '') { + IPS_LogMessage('Abrechnung', "⚠ Keine Segmente erzeugt, Fallback auf Gesamtzeitraum"); + $startValue = $this->GetValueAt($varId, $from, false); + $endValue = $this->GetValueAt($varId, $to, true); + $verbrauch = max(0, $endValue - $startValue); + $rows = " + + {$meter['name']} + {$type} + " . date('d.m.Y H:i', $from) . " + " . date('d.m.Y H:i', $to) . " + " . number_format($startValue, 2) . " + " . number_format($endValue, 2) . " + " . number_format($verbrauch, 2) . " + 0 + 0.00 + "; + } + IPS_LogMessage('Abrechnung', sprintf("✅ [AddMeterToPDFRow] Fertig: %.2f CHF total, %d Segmente", $totalCost, $segmentIndex - 1)); return ['row' => $rows, 'value' => $totalCost];