diff --git a/Abrechnung/module.php b/Abrechnung/module.php index 4ab5444..db45ecf 100644 --- a/Abrechnung/module.php +++ b/Abrechnung/module.php @@ -277,9 +277,8 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) return ['row' => '', 'value' => 0]; } - // đ§© Einheitstyp tolerant abgleichen - $filteredTariffs = []; - foreach ($tariffs as $t) { + // --- Relevante Tarife nach Typ filtern --- + $filteredTariffs = array_filter($tariffs, function ($t) use ($type) { $tariffType = strtolower(trim($t['unit_type'] ?? '')); $typeNorm = strtolower(trim($type)); @@ -289,121 +288,93 @@ private function AddMeterToPDFRow($meter, $tariffs, $from, $to, $type) 'kaltwasser' => ['kaltwasser', 'wasser', 'kww'], 'wĂ€rme' => ['wĂ€rme', 'heizung', 'heat'] ]; - - if (in_array($tariffType, $map[$typeNorm] ?? []) || $tariffType == $typeNorm) { - $filteredTariffs[] = $t; - } - } - - IPS_LogMessage('Abrechnung', "đ Suche Tarife fĂŒr Typ '$type': gefunden " . count($filteredTariffs) . " Treffer"); - foreach ($filteredTariffs as $t) { - IPS_LogMessage('Abrechnung', " Tarif '{$t['unit_type']}' von " . json_encode($t['start']) . " bis " . json_encode($t['end']) . " | {$t['price']} Rp"); - } + return in_array($tariffType, $map[$typeNorm] ?? []) || $tariffType === $typeNorm; + }); if (empty($filteredTariffs)) { IPS_LogMessage('Abrechnung', "â Keine passenden Tarife fĂŒr $type gefunden"); return ['row' => '', 'value' => 0]; } - // đč Datumsfelder sicher umwandeln + // --- Tarife sicher in ZeitrĂ€ume umwandeln --- foreach ($filteredTariffs as &$t) { - if (is_array($t['start'])) { - $t['start_ts'] = mktime(0, 0, 0, $t['start']['month'], $t['start']['day'], $t['start']['year']); - } else { - $t['start_ts'] = strtotime($t['start'] . ' 00:00:00'); - } - - if (is_array($t['end'])) { - $t['end_ts'] = mktime(23, 59, 59, $t['end']['month'], $t['end']['day'], $t['end']['year']); - } else { - $t['end_ts'] = strtotime($t['end'] . ' 23:59:59'); - } - - if ($t['start_ts'] === false || $t['end_ts'] === false) { - IPS_LogMessage('Abrechnung', "â UngĂŒltiges Tarifdatum nach Umwandlung: " . json_encode($t)); - } else { - IPS_LogMessage('Abrechnung', "â Tarifzeitraum erkannt: " . date('d.m.Y', $t['start_ts']) . " - " . date('d.m.Y', $t['end_ts'])); + $t['start_ts'] = is_numeric($t['start']) ? intval($t['start']) : strtotime($t['start']); + $t['end_ts'] = is_numeric($t['end']) ? intval($t['end']) : strtotime($t['end']); + if (!$t['start_ts'] || !$t['end_ts']) { + IPS_LogMessage('Abrechnung', "â UngĂŒltiger Tarifzeitraum: " . json_encode($t)); + continue; } } unset($t); - // Nach Startzeit sortieren + // Sortiere Tarife nach Startzeit usort($filteredTariffs, fn($a, $b) => $a['start_ts'] <=> $b['start_ts']); $current = $from; while ($current < $to) { - $activeTariff = null; - $segmentStart = $current; - $segmentEnd = $to; - - // --- passenden Tarif finden (einfach & robust) --- + // Finde aktiven Tarif fĂŒr diesen Zeitpunkt $activeTariff = null; foreach ($filteredTariffs as $t) { - if ($t['start_ts'] <= $segmentStart && $segmentStart <= $t['end_ts']) { + if ($t['start_ts'] <= $current && $current <= $t['end_ts']) { $activeTariff = $t; break; } } - if ($activeTariff) { - // Tarif aktiv: Segment geht bis Tarifende oder Rechnungsende - $segmentEnd = min($activeTariff['end_ts'], $to); - $tariffPrice = floatval($activeTariff['price']); - $tariffLabel = number_format($tariffPrice, 2); - } else { - // Kein Tarif aktiv: bis zum nĂ€chsten Tarifstart (oder Rechnungsende) mit 0 Rp + // Wenn kein aktiver Tarif, nimm nĂ€chsten oder rechne 0 Rp + if (!$activeTariff) { $nextStart = $to; foreach ($filteredTariffs as $t) { - if ($t['start_ts'] > $segmentStart && $t['start_ts'] < $nextStart) { + if ($t['start_ts'] > $current && $t['start_ts'] < $nextStart) { $nextStart = $t['start_ts']; } } $segmentEnd = min($nextStart, $to); $tariffPrice = 0.0; $tariffLabel = 'kein Tarif'; + } else { + $segmentEnd = min($activeTariff['end_ts'], $to); + $tariffPrice = floatval($activeTariff['price']); + $tariffLabel = number_format($tariffPrice, 2); } - - // Archivwerte lesen - $startVal = $this->GetValueAt($varId, $segmentStart, true); + // --- Verbrauch fĂŒr diesen Zeitraum --- + $startVal = $this->GetValueAt($varId, $current, true); $endVal = $this->GetValueAt($varId, $segmentEnd, true); - if ($startVal === null || $endVal === null) { - IPS_LogMessage('Abrechnung', "â Keine Archivwerte fĂŒr {$meter['name']} ($type) im Zeitraum " . date('d.m.Y H:i', $segmentStart) . " - " . date('d.m.Y H:i', $segmentEnd)); + IPS_LogMessage('Abrechnung', "â Keine Werte fĂŒr {$meter['name']} im Zeitraum " . date('d.m.Y H:i', $current) . " - " . date('d.m.Y H:i', $segmentEnd)); $current = $segmentEnd + 1; continue; } $diff = max(0, $endVal - $startVal); - $costCHF = ($tariffPrice / 100) * $diff; - - IPS_LogMessage('Abrechnung', "â {$meter['name']} ($type): " . date('d.m.Y H:i', $segmentStart) . " bis " . date('d.m.Y H:i', $segmentEnd) . " | Tarif {$tariffLabel} Rp | Verbrauch {$diff}"); + $costCHF = round(($tariffPrice / 100) * $diff, 2); + $totalCost += $costCHF; + // --- Ausgabezeile --- $rows .= "