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)