From a094dc925b2993b4788904b5291fc6db12f58aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=A4fliger?= Date: Tue, 4 Nov 2025 15:06:45 +0100 Subject: [PATCH] no message --- Abrechnung/module.php | 144 +++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/Abrechnung/module.php b/Abrechnung/module.php index 8cbb939..e3c696d 100644 --- a/Abrechnung/module.php +++ b/Abrechnung/module.php @@ -215,114 +215,88 @@ public function GenerateInvoices() return 0.0; } - private function GetValueAt(int $varId, int $timestamp) - { - $archiveID = @IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; - if (!$archiveID || !IPS_VariableExists($varId)) return null; +private function GetValueAt(int $varId, int $timestamp) +{ + $archiveID = @IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; + if (!$archiveID || !IPS_VariableExists($varId)) return null; - $values = @AC_GetLoggedValues($archiveID, $varId, $timestamp - 3600, $timestamp + 3600, 1); - if ($values && count($values) > 0) { - return floatval($values[0]['Value']); - } - return floatval(GetValue($varId)); + // 1. Werte **vor und nach** dem Timestamp holen + $valuesBefore = @AC_GetLoggedValues($archiveID, $varId, $timestamp - 86400, $timestamp, 1); // letzter Wert <= Timestamp + $valuesAfter = @AC_GetLoggedValues($archiveID, $varId, $timestamp, $timestamp + 86400, 1); // erster Wert >= Timestamp + + if ($valuesBefore && count($valuesBefore) > 0) { + $before = floatval($valuesBefore[count($valuesBefore)-1]['Value']); + } else { + $before = null; } + if ($valuesAfter && count($valuesAfter) > 0) { + $after = floatval($valuesAfter[0]['Value']); + } else { + $after = null; + } + + // Priorität: exakter Wert >= Timestamp, sonst letzter Wert davor + if ($after !== null) return $after; + if ($before !== null) return $before; + + // Fallback auf aktuellen Wert + return floatval(GetValue($varId)); +} + private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) { $startVal = $this->GetValueAt($meter['var_consumption'], $from); $endVal = $this->GetValueAt($meter['var_consumption'], $to); - if ($startVal === null || $endVal === null) { - IPS_LogMessage('Abrechnung', "❌ Kein Wert für {$meter['name']} ($type)"); - return ['row' => '', 'value' => 0]; - } + if ($startVal === null || $endVal === null) return ['row' => '', 'value' => 0]; $totalDiff = max(0, $endVal - $startVal); - if ($totalDiff <= 0) { - IPS_LogMessage('Abrechnung', "⚠️ Kein Verbrauch für {$meter['name']} ($type): Start=$startVal, Ende=$endVal"); - return ['row' => '', 'value' => 0]; - } - - IPS_LogMessage('Abrechnung', "📊 {$meter['name']} ($type): Verbrauch gesamt=$totalDiff"); + if ($totalDiff <= 0) return ['row' => '', 'value' => 0]; $rows = ''; $totalCost = 0.0; - $foundTariff = false; - foreach ($tariffs as $t) { - if (!isset($t['start'], $t['end'], $t['price'], $t['unit_type'])) continue; - if (strtolower($t['unit_type']) != strtolower($type)) continue; + // Alle Tarife dieses Typs prüfen + foreach ($tariffs as $t) { + if (strtolower($t['unit_type']) != strtolower($type)) continue; - $tariffStart = strtotime($t['start']); - $tariffEnd = strtotime($t['end']); - if ($tariffEnd < $from || $tariffStart > $to) continue; + $tariffStart = strtotime($t['start']); + $tariffEnd = strtotime($t['end']); - $foundTariff = true; + // Zeitliche Überschneidung mit Abrechnungszeitraum? + if ($tariffEnd < $from || $tariffStart > $to) continue; - $sectionStart = max($from, $tariffStart); - $sectionEnd = min($to, $tariffEnd); - $sectionDuration = $sectionEnd - $sectionStart; - $totalDuration = $to - $from; + // Überschneidung bestimmen + $sectionStart = max($from, $tariffStart); + $sectionEnd = min($to, $tariffEnd); + $sectionDuration = $sectionEnd - $sectionStart; + $totalDuration = $to - $from; - if ($sectionDuration <= 0) continue; + if ($sectionDuration <= 0) continue; - $sectionFraction = $sectionDuration / $totalDuration; - $sectionDiff = $totalDiff * $sectionFraction; + // Anteil des Gesamtverbrauchs nach Zeitanteil + $sectionFraction = $sectionDuration / $totalDuration; + $sectionDiff = $totalDiff * $sectionFraction; - $tariffRp = floatval($t['price']); - $costCHF = ($tariffRp / 100) * $sectionDiff; + $tariffRp = floatval($t['price']); + $costCHF = ($tariffRp / 100) * $sectionDiff; - IPS_LogMessage('Abrechnung', "→ Tarif {$t['price']} Rp vom " . date('d.m.Y', $tariffStart) . " bis " . date('d.m.Y', $tariffEnd) . - " deckt " . date('d.m.Y', $sectionStart) . "–" . date('d.m.Y', $sectionEnd) . " ab, Anteil=" . round($sectionFraction*100,1) . "%"); + $rows .= " + + {$meter['name']} + $type + " . date('d.m.Y', $sectionStart) . " + " . date('d.m.Y', $sectionEnd) . " + " . number_format($sectionDiff, 2) . " + " . number_format($tariffRp, 2) . " + " . number_format($costCHF, 2) . " + "; - $rows .= " - - {$meter['name']} - $type - " . date('d.m.Y', $sectionStart) . " - " . date('d.m.Y', $sectionEnd) . " - " . number_format($sectionDiff, 2) . " - " . number_format($tariffRp, 2) . " - " . number_format($costCHF, 2) . " - "; - - $totalCost += $costCHF; - } - - if (!$foundTariff) { - IPS_LogMessage('Abrechnung', "⚠️ Kein Tarif für $type im Zeitraum gefunden"); - } - - return ['row' => $rows, 'value' => $totalCost]; -} - - private function GetValueAt(int $varId, int $timestamp) - { - $archiveID = @IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; - if (!$archiveID || !IPS_VariableExists($varId)) { - IPS_LogMessage('Abrechnung', "⚠️ Archiv oder Variable fehlt für ID $varId"); - return null; + $totalCost += $costCHF; } - // Letzter Wert vor oder gleich Timestamp - $before = @AC_GetLoggedValues($archiveID, $varId, $timestamp - 86400 * 60, $timestamp, 1); - if ($before && count($before) > 0) { - $val = floatval($before[0]['Value']); - IPS_LogMessage('Abrechnung', "📉 Wert vor $timestamp: $val"); - return $val; - } - - // Erster Wert nach Timestamp - $after = @AC_GetLoggedValues($archiveID, $varId, $timestamp, $timestamp + 86400 * 60, 1); - if ($after && count($after) > 0) { - $val = floatval($after[0]['Value']); - IPS_LogMessage('Abrechnung', "📈 Wert nach $timestamp: $val"); - return $val; - } - - // Fallback auf aktuellen Wert - $val = floatval(GetValue($varId)); - IPS_LogMessage('Abrechnung', "⚙️ Fallback Wert (aktuell): $val"); - return $val; + return ['row' => $rows, 'value' => $totalCost]; } + } \ No newline at end of file