diff --git a/Abrechnung/module.php b/Abrechnung/module.php index 916ed08..6679f8f 100644 --- a/Abrechnung/module.php +++ b/Abrechnung/module.php @@ -89,7 +89,7 @@ class Abrechnung extends IPSModule return false; } - // Stromkosten einmal für alle User berechnen + // Stromkosten einmal für alle User berechnen (15-Minuten-Logik) $this->CalculateAllPowerCosts($power, $tariffs, $from, $to); $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); @@ -119,7 +119,7 @@ class Abrechnung extends IPSModule $html .= "

⚡ Stromkosten

" . $powerResult['html']; $totalPower = $powerResult['sum']; - // Nebenkosten (Wasser/Wärme) + // Nebenkosten (Wasser/Wärme) – einfache Differenz von Beginn bis Ende $additionalResult = $this->CalculateAdditionalCosts($water, $tariffs, $user['id'], $from, $to); $html .= "

💧 Nebenkosten (Wasser/Wärme)

" . $additionalResult['html']; $totalAdditional = $additionalResult['sum']; @@ -216,14 +216,14 @@ class Abrechnung extends IPSModule // Verhältnis PV / Netz pro User if ($impTotal <= $expTotal && $expTotal > 0.0) { - $ratio = $impTotal / $expTotal; - $pvCoversAll = true; + $ratio = $impTotal / $expTotal; + $pvCoversAll = true; } elseif ($impTotal > 0.0) { - $ratio = $expTotal / $impTotal; - $pvCoversAll = false; + $ratio = $expTotal / $impTotal; + $pvCoversAll = false; } else { - $ratio = 0.0; - $pvCoversAll = true; + $ratio = 0.0; + $pvCoversAll = true; } // Werte pro Zähler verteilen @@ -359,62 +359,75 @@ class Abrechnung extends IPSModule return ['html' => $html, 'sum' => $total]; } -private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) -{ - $varId = $meter['var_consumption']; + private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) + { + $rows = ''; + $totalCost = 0.0; + $usedTariffs = []; + $varId = $meter['var_consumption']; - if (!IPS_VariableExists($varId)) { - return ['row' => '', 'value' => 0, 'tariffs' => []]; - } - - // ---- 1) Start- und Endwerte direkt holen ---- - $startValue = $this->GetValueAt($varId, $from, false); // letzter Wert VOR dem Start - $endValue = $this->GetValueAt($varId, $to, true); // erster Wert NACH dem Ende - - if ($startValue === null || $endValue === null) { - return ['row' => '', 'value' => 0, 'tariffs' => []]; - } - - // ---- 2) Verbrauch simple Differenz ---- - $verbrauch = max(0, $endValue - $startValue); - - // ---- 3) passenden Tarif suchen ---- - $tariffPrice = 0.0; - foreach ($tariffs as $t) { - if (strtolower(trim($t['unit_type'] ?? '')) === strtolower(trim($type))) { - $tariffPrice = floatval($t['price']); - break; + if (!IPS_VariableExists($varId)) { + return ['row' => '', 'value' => 0, 'tariffs' => []]; } + + // Relevante Tarife nach Typ filtern + $filteredTariffs = array_filter($tariffs, fn($t) => + strtolower(trim($t['unit_type'] ?? '')) === strtolower(trim($type)) + ); + + $activeTariff = null; + foreach ($filteredTariffs as $t) { + $startTs = $this->toUnixTs($t['start'], false); + $endTs = $this->toUnixTs($t['end'], true); + if ($startTs === null || $endTs === null) { + continue; + } + // Tarif überlappt den Abrechnungszeitraum + if ($endTs < $from || $startTs > $to) { + continue; + } + $activeTariff = [ + 'start' => $startTs, + 'end' => $endTs, + 'price' => (float)$t['price'] + ]; + $usedTariffs[] = $activeTariff; + break; // erster passender Tarif reicht + } + + $tariffPrice = $activeTariff ? $activeTariff['price'] : 0.0; + + // Verbrauch = letzter Wert vor/gleich "to" minus letzter Wert vor/gleich "from" + $startValue = $this->GetValueAt($varId, $from, false); + $endValue = $this->GetValueAt($varId, $to, false); + + if ($startValue === null || $endValue === null) { + return ['row' => '', 'value' => 0, 'tariffs' => []]; + } + + $verbrauch = max(0, $endValue - $startValue); + $kosten = round(($tariffPrice / 100) * $verbrauch, 2); + $totalCost = $kosten; + + $rows .= " + {$meter['name']} + {$type} + " . date('d.m.Y', $from) . " + " . date('d.m.Y', $to) . " + " . number_format($startValue, 2) . " + " . number_format($endValue, 2) . " + " . number_format($verbrauch, 2) . " + " . number_format($tariffPrice, 2) . " + " . number_format($kosten, 2) . " + "; + + if ($rows === '') { + return ['row' => '', 'value' => 0, 'tariffs' => []]; + } + + return ['row' => $rows, 'value' => $totalCost, 'tariffs' => array_values($usedTariffs)]; } - // ---- 4) Kosten (Rp → CHF) ---- - $kosten = round(($tariffPrice / 100) * $verbrauch, 2); - - // ---- 5) Tabellenzeile ---- - $row = " - {$meter['name']} - {$type} - " . date('d.m.Y', $from) . " - " . date('d.m.Y', $to) . " - " . number_format($startValue, 2) . " - " . number_format($endValue, 2) . " - " . number_format($verbrauch, 2) . " - " . number_format($tariffPrice, 2) . " - " . number_format($kosten, 2) . " - "; - - return [ - 'row' => $row, - 'value' => $kosten, - 'tariffs' => [[ - 'start' => $from, - 'end' => $to, - 'price' => $tariffPrice - ]] - ]; -} - - // ====================== Hilfsfunktionen ====================== private function GetValueAt($varId, $timestamp, $nearestAfter = true)