diff --git a/Abrechnung/module.php b/Abrechnung/module.php
index b9344ae..ddc4fcb 100644
--- a/Abrechnung/module.php
+++ b/Abrechnung/module.php
@@ -95,11 +95,10 @@ class Abrechnung extends IPSModule
$pdf->SetAutoPageBreak(true, 20);
$pdf->SetFont('dejavusans', '', 9);
- foreach ($users as $user) {
- $pdf->AddPage();
- $html = $this->BuildUserInvoice($user, $power, $water, $tariffs, $from, $to);
- $pdf->writeHTML($html);
- }
+ foreach ($users as $user) {
+ IPS_LogMessage('Abrechnung', '→ Erstelle Seite für Benutzer: ' . $user['name']);
+ $this->BuildUserInvoice($pdf, $user, $power, $water, $tariffs, $from, $to);
+ }
return $pdf->Output('Abrechnung.pdf', 'S');
}
@@ -107,122 +106,104 @@ class Abrechnung extends IPSModule
// ===========================================================
// 🧱 Layout / PDF-Aufbau pro Benutzerseite
// ===========================================================
- private function BuildUserInvoice($user, $power, $water, $tariffs, $from, $to)
+ private function CalculatePowerCosts(array $powerMeters, array $tariffs, int $userId, int $from, int $to): array
{
- $stromRows = '';
- $stromTotal = 0.0;
- $stromTariffsUsed = [];
+ $html = "
+
+ | Zähler |
+ Typ |
+ Start |
+ Ende |
+ Zählerstand Start |
+ Zählerstand Ende |
+ Verbrauch |
+ Tarif (Rp) |
+ Kosten (CHF) |
+
";
+ $total = 0.0;
- $nebenRows = '';
- $nebenTotal = 0.0;
- $nebenTariffsUsed = [];
-
- // ---------- Stromkosten ----------
- foreach ($power as $m) {
- if ($m['user_id'] != $user['id']) continue;
- $res = $this->AddMeterToPDFRow($m, $tariffs, $from, $to, 'Strombezug');
- $stromRows .= $res['row'];
- $stromTotal += $res['value'];
+ foreach ($powerMeters as $m) {
+ if ($m['user_id'] != $userId) continue;
+ $cost = $this->AddMeterToPDFRow($m, $tariffs, $from, $to, 'Strombezug');
+ $html .= $cost['row'];
+ $total += $cost['value'];
}
- // ---------- Nebenkosten ----------
- foreach ($water as $m) {
- if ($m['user_id'] != $user['id']) continue;
+ $html .= "
+
+ | Total Stromkosten: |
+ " . number_format($total, 2) . " |
+
+
";
+
+ return ['html' => $html, 'sum' => $total];
+}
+
+private function CalculatePowerCosts(array $powerMeters, array $tariffs, int $userId, int $from, int $to): array
+{
+ $html = "
+
+ | Zähler |
+ Typ |
+ Start |
+ Ende |
+ Zählerstand Start |
+ Zählerstand Ende |
+ Verbrauch |
+ Tarif (Rp) |
+ Kosten (CHF) |
+
";
+ $total = 0.0;
+
+ foreach ($powerMeters as $m) {
+ if ($m['user_id'] != $userId) continue;
+ $cost = $this->AddMeterToPDFRow($m, $tariffs, $from, $to, 'Strombezug');
+ $html .= $cost['row'];
+ $total += $cost['value'];
+ }
+
+ $html .= "
+
+ | Total Stromkosten: |
+ " . number_format($total, 2) . " |
+
+
";
+
+ return ['html' => $html, 'sum' => $total];
+}
+
+private function CalculateAdditionalCosts(array $waterMeters, array $tariffs, int $userId, int $from, int $to): array
+{
+ $html = "
+
+ | Zähler |
+ Typ |
+ Start |
+ Ende |
+ Zählerstand Start |
+ Zählerstand Ende |
+ Verbrauch |
+ Tarif (Rp) |
+ Kosten (CHF) |
+
";
+ $total = 0.0;
+
+ foreach ($waterMeters as $m) {
+ if ($m['user_id'] != $userId) continue;
$type = $m['meter_type'] ?? 'Warmwasser';
- $res = $this->AddMeterToPDFRow($m, $tariffs, $from, $to, $type);
- $nebenRows .= $res['row'];
- $nebenTotal += $res['value'];
+ $cost = $this->AddMeterToPDFRow($m, $tariffs, $from, $to, $type);
+ $html .= $cost['row'];
+ $total += $cost['value'];
}
- // ---------- Alle Tarife gruppieren ----------
- $tariffGroups = [];
- foreach ($tariffs as $t) {
- $type = ucfirst(strtolower($t['unit_type'] ?? 'Unbekannt'));
- $sTs = $this->toUnixTs($t['start'], false);
- $eTs = $this->toUnixTs($t['end'], true);
- if ($sTs && $eTs) {
- $period = date('d.m.Y', $sTs) . ' – ' . date('d.m.Y', $eTs);
- $price = number_format(floatval($t['price']), 2);
- $tariffGroups[$type][] = "{$period}: {$price} Rp";
- }
- }
-
- // ---------- Gesamtsummen ----------
- $gesamtTotal = $stromTotal + $nebenTotal;
-
- // ---------- Tabellenstil ----------
- $tableStyle = "border-collapse:collapse;width:100%;font-size:8px;";
- $cellStyle = "border:0.3px solid #bbb;padding:3px;vertical-align:middle;";
-
- // ---------- Kopfbereich ----------
- $html = "
- Rechnung für {$user['name']}
- {$user['address']}
{$user['city']}
- Abrechnungszeitraum: " . date('d.m.Y', $from) . " – " . date('d.m.Y', $to) . "
";
-
- // ---------- Stromkosten ----------
$html .= "
- ⚡ Stromkosten
-
-
- | Zähler |
- Typ |
- Startzeit |
- Endzeit |
- Start |
- Ende |
- Verbrauch |
- Tarif (Rp) |
- Kosten (CHF) |
+
+ | Total Nebenkosten: |
+ " . number_format($total, 2) . " |
- {$stromRows}
-
- | Total Stromkosten: |
- " . number_format($stromTotal, 2) . " |
-
-
";
+
";
- // ---------- Nebenkosten ----------
- $html .= "
- 💧 Nebenkosten (Wasser & Wärme)
-
-
- | Zähler |
- Typ |
- Startzeit |
- Endzeit |
- Start |
- Ende |
- Verbrauch |
- Tarif (Rp) |
- Kosten (CHF) |
-
- {$nebenRows}
-
- | Total Nebenkosten: |
- " . number_format($nebenTotal, 2) . " |
-
-
";
-
- // ---------- Tarife (alle Typen) ----------
- if (!empty($tariffGroups)) {
- $html .= "📋 Angewendete Tarife
";
- foreach ($tariffGroups as $type => $entries) {
- $html .= "| {$type} |
";
- foreach ($entries as $line) {
- $html .= "| {$line} |
";
- }
- }
- $html .= "
";
- }
-
- // ---------- Gesamttotal ----------
- $html .= "
-
- 💰 Gesamttotal: " . number_format($gesamtTotal, 2) . " CHF
-
";
-
- return $html;
+ return ['html' => $html, 'sum' => $total];
}
@@ -302,7 +283,7 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type)
date_default_timezone_set('Europe/Zurich');
- // 🔹 Passende Tarife nach Typ filtern
+ // 🔹 Filtere relevante Tarife nach Typ
$filteredTariffs = array_filter($tariffs, function ($t) use ($type) {
return strtolower(trim($t['unit_type'] ?? '')) === strtolower(trim($type));
});
@@ -312,7 +293,7 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type)
return ['row' => '', 'value' => 0];
}
- // 🔹 Zeitstempel konvertieren und sortieren
+ // 🔹 Normiere Zeiträume
foreach ($filteredTariffs as &$t) {
$t['start_ts'] = $this->toUnixTs($t['start'], false);
$t['end_ts'] = $this->toUnixTs($t['end'], true);
@@ -323,6 +304,7 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type)
$currentStart = $from;
while ($currentStart < $to) {
+ // 🔹 Aktiven Tarif suchen
$activeTariff = null;
foreach ($filteredTariffs as $t) {
if (($t['start_ts'] ?? 0) <= $currentStart && $currentStart <= ($t['end_ts'] ?? 0)) {
@@ -342,32 +324,35 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type)
$tariffEnd = intval($activeTariff['end_ts']);
$tariffPrice = floatval($activeTariff['price']);
+ $tariffLabel = number_format($tariffPrice, 2, ',', '');
- $startValue = $this->GetValueAt($varId, $currentStart, true);
- $segmentEnd = ($tariffEnd < $to) ? $tariffEnd : $to;
- $endValue = $this->GetValueAt($varId, $segmentEnd, true);
+ // 🔹 Werte aus Archiv lesen
+ $startValue = $this->GetValueAt($varId, $currentStart, true);
+ $segmentEnd = ($tariffEnd < $to) ? $tariffEnd : $to;
+ $endValue = $this->GetValueAt($varId, $segmentEnd, true);
if ($startValue === null || $endValue === null) break;
- $verbrauch = max(0, $endValue - $startValue);
- $kosten = round(($tariffPrice / 100) * $verbrauch, 2);
- $totalCost += $kosten;
+ $verbrauch = max(0, $endValue - $startValue);
+ $kosten = round(($tariffPrice / 100) * $verbrauch, 2);
+ $totalCost += $kosten;
+ // 🔹 Kurze Datumsangaben
$startDate = date('d.m.Y', $currentStart);
$endDate = date('d.m.Y', $segmentEnd);
- // 🧾 TCPDF-kompatible Tabellenzeile (sichtbare Linien)
+ // 🔹 Tabellenzeile mit sichtbaren Linien
$rows .= "
-
- | {$meter['name']} |
- {$type} |
- {$startDate} |
- {$endDate} |
- " . number_format($startValue, 2) . " |
- " . number_format($endValue, 2) . " |
- " . number_format($verbrauch, 2) . " |
- " . number_format($tariffPrice, 2) . " |
- " . number_format($kosten, 2) . " |
+
+ | {$meter['name']} |
+ {$type} |
+ {$startDate} |
+ {$endDate} |
+ " . number_format($startValue, 2) . " |
+ " . number_format($endValue, 2) . " |
+ " . number_format($verbrauch, 2) . " |
+ " . $tariffLabel . " |
+ " . number_format($kosten, 2) . " |
";
if ($tariffEnd < $to) {
@@ -377,36 +362,26 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type)
}
}
- // Fallback (keine Segmente)
+ // 🔹 Fallback – kein Segment gefunden
if ($rows === '') {
$startVal = $this->GetValueAt($varId, $from, false);
$endVal = $this->GetValueAt($varId, $to, true);
$verbrauch = max(0, $endVal - $startVal);
$rows = "
-
- | {$meter['name']} |
- {$type} |
- " . date('d.m.Y', $from) . " |
- " . date('d.m.Y', $to) . " |
- " . number_format($startVal, 2) . " |
- " . number_format($endVal, 2) . " |
- " . number_format($verbrauch, 2) . " |
- 0.00 |
- 0.00 |
+
+ | {$meter['name']} |
+ {$type} |
+ " . date('d.m.Y', $from) . " |
+ " . date('d.m.Y', $to) . " |
+ " . number_format($startVal, 2) . " |
+ " . number_format($endVal, 2) . " |
+ " . number_format($verbrauch, 2) . " |
+ 0.00 |
+ 0.00 |
";
}
- // 🧾 Totalsumme in separater, deutlich sichtbarer Zeile
- $rows .= "
-
- | Total {$type}: |
- " . number_format($totalCost, 2) . " |
-
";
-
- // Komplett in eine sichtbare Tabelle einbetten (damit TCPDF Linien rendert)
- $table = "";
-
- return ['row' => $table, 'value' => $totalCost];
+ return ['row' => $rows, 'value' => $totalCost];
}