diff --git a/Abrechnung/module.php b/Abrechnung/module.php index 5678267..8cbb939 100644 --- a/Abrechnung/module.php +++ b/Abrechnung/module.php @@ -231,55 +231,98 @@ 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) return ['row' => '', 'value' => 0]; + if ($startVal === null || $endVal === null) { + IPS_LogMessage('Abrechnung', "❌ Kein Wert für {$meter['name']} ($type)"); + return ['row' => '', 'value' => 0]; + } $totalDiff = max(0, $endVal - $startVal); - if ($totalDiff <= 0) return ['row' => '', 'value' => 0]; + 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"); $rows = ''; $totalCost = 0.0; + $foundTariff = false; - // Alle Tarife dieses Typs prüfen - foreach ($tariffs as $t) { - if (strtolower($t['unit_type']) != strtolower($type)) continue; + foreach ($tariffs as $t) { + if (!isset($t['start'], $t['end'], $t['price'], $t['unit_type'])) continue; + if (strtolower($t['unit_type']) != strtolower($type)) continue; - $tariffStart = strtotime($t['start']); - $tariffEnd = strtotime($t['end']); + $tariffStart = strtotime($t['start']); + $tariffEnd = strtotime($t['end']); + if ($tariffEnd < $from || $tariffStart > $to) continue; - // Zeitliche Überschneidung mit Abrechnungszeitraum? - if ($tariffEnd < $from || $tariffStart > $to) continue; + $foundTariff = true; - // Überschneidung bestimmen - $sectionStart = max($from, $tariffStart); - $sectionEnd = min($to, $tariffEnd); - $sectionDuration = $sectionEnd - $sectionStart; - $totalDuration = $to - $from; + $sectionStart = max($from, $tariffStart); + $sectionEnd = min($to, $tariffEnd); + $sectionDuration = $sectionEnd - $sectionStart; + $totalDuration = $to - $from; - if ($sectionDuration <= 0) continue; + if ($sectionDuration <= 0) continue; - // Anteil des Gesamtverbrauchs nach Zeitanteil - $sectionFraction = $sectionDuration / $totalDuration; - $sectionDiff = $totalDiff * $sectionFraction; + $sectionFraction = $sectionDuration / $totalDuration; + $sectionDiff = $totalDiff * $sectionFraction; - $tariffRp = floatval($t['price']); - $costCHF = ($tariffRp / 100) * $sectionDiff; + $tariffRp = floatval($t['price']); + $costCHF = ($tariffRp / 100) * $sectionDiff; - $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) . " - "; + 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) . "%"); - $totalCost += $costCHF; - } + $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) . " + "; - return ['row' => $rows, 'value' => $totalCost]; + $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; + } + + // 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; + } } \ No newline at end of file