no message
This commit is contained in:
@@ -5,17 +5,15 @@
|
|||||||
"caption": "🧾 Abrechnungseinstellungen"
|
"caption": "🧾 Abrechnungseinstellungen"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Image",
|
"type": "SelectMedia",
|
||||||
"name": "Logo",
|
"name": "LogoMediaID",
|
||||||
"caption": "Firmenlogo"
|
"caption": "Logo auswählen"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "ValidationTextBox",
|
"type": "ValidationTextBox",
|
||||||
"name": "FooterText",
|
"name": "FooterText",
|
||||||
"caption": "Fusszeile"
|
"caption": "Fusszeile"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
"type": "List",
|
"type": "List",
|
||||||
|
|||||||
@@ -3,19 +3,33 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
include_once __DIR__ . '/libs/vendor/autoload.php'; // TCPDF via Composer
|
include_once __DIR__ . '/libs/vendor/autoload.php'; // TCPDF via Composer
|
||||||
|
|
||||||
|
/**
|
||||||
class PDFWithFooter extends TCPDF {
|
* Eigene TCPDF-Klasse mit Logo im Header und Text in der Fusszeile
|
||||||
|
*/
|
||||||
|
class InvoicePDF extends TCPDF
|
||||||
|
{
|
||||||
|
public $logoFile = null;
|
||||||
public $footerText = '';
|
public $footerText = '';
|
||||||
|
|
||||||
public function Footer() {
|
public function Header()
|
||||||
|
{
|
||||||
|
if ($this->logoFile !== null && file_exists($this->logoFile)) {
|
||||||
|
// x, y, width in mm
|
||||||
|
$this->Image($this->logoFile, 15, 10, 40);
|
||||||
|
$this->SetY(28);
|
||||||
|
} else {
|
||||||
|
$this->SetY(15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Footer()
|
||||||
|
{
|
||||||
$this->SetY(-15);
|
$this->SetY(-15);
|
||||||
$this->SetFont('dejavusans', '', 8);
|
$this->SetFont('dejavusans', '', 8);
|
||||||
$this->Cell(0, 10, $this->footerText, 0, 0, 'C');
|
$this->Cell(0, 10, $this->footerText, 0, 0, 'C');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Abrechnung extends IPSModule
|
class Abrechnung extends IPSModule
|
||||||
{
|
{
|
||||||
public function Create()
|
public function Create()
|
||||||
@@ -26,7 +40,7 @@ class Abrechnung extends IPSModule
|
|||||||
$this->RegisterPropertyString('PowerMeters', '[]');
|
$this->RegisterPropertyString('PowerMeters', '[]');
|
||||||
$this->RegisterPropertyString('WaterMeters', '[]');
|
$this->RegisterPropertyString('WaterMeters', '[]');
|
||||||
$this->RegisterPropertyString('Tariffs', '[]');
|
$this->RegisterPropertyString('Tariffs', '[]');
|
||||||
$this->RegisterPropertyString('Logo', '');
|
$this->RegisterPropertyInteger('LogoMediaID', 0);
|
||||||
$this->RegisterPropertyString('FooterText', 'Belevo AG • 6122 Menznau • www.belevo.ch');
|
$this->RegisterPropertyString('FooterText', 'Belevo AG • 6122 Menznau • www.belevo.ch');
|
||||||
|
|
||||||
$this->RegisterVariableInteger('FromDate', 'Startdatum', '~UnixTimestamp', 1);
|
$this->RegisterVariableInteger('FromDate', 'Startdatum', '~UnixTimestamp', 1);
|
||||||
@@ -107,36 +121,36 @@ class Abrechnung extends IPSModule
|
|||||||
// Stromkosten einmal für alle User berechnen (15-Minuten-Logik)
|
// Stromkosten einmal für alle User berechnen (15-Minuten-Logik)
|
||||||
$this->CalculateAllPowerCosts($power, $tariffs, $from, $to);
|
$this->CalculateAllPowerCosts($power, $tariffs, $from, $to);
|
||||||
|
|
||||||
$pdf = new PDFWithFooter('P', 'mm', 'A4', true, 'UTF-8', false);
|
// Logo & Fusszeile vorbereiten
|
||||||
$pdf->footerText = $this->ReadPropertyString('FooterText');
|
$logoFile = $this->GetLogoFile();
|
||||||
|
$footerText = $this->ReadPropertyString('FooterText');
|
||||||
|
|
||||||
|
// PDF-Objekt
|
||||||
|
$pdf = new InvoicePDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
||||||
|
$pdf->logoFile = $logoFile;
|
||||||
|
$pdf->footerText = $footerText;
|
||||||
|
|
||||||
$pdf->SetCreator('IPSymcon Abrechnung');
|
$pdf->SetCreator('IPSymcon Abrechnung');
|
||||||
$pdf->SetMargins(15, 15, 15);
|
// Oben mehr Platz für Logo lassen
|
||||||
|
$pdf->SetMargins(15, 35, 15);
|
||||||
$pdf->SetAutoPageBreak(true, 20);
|
$pdf->SetAutoPageBreak(true, 20);
|
||||||
$pdf->SetFont('dejavusans', '', 9);
|
$pdf->SetFont('dejavusans', '', 8);
|
||||||
|
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
|
$pdf->AddPage();
|
||||||
$this->BuildUserInvoice($pdf, $user, $power, $water, $tariffs, $from, $to);
|
$this->BuildUserInvoice($pdf, $user, $power, $water, $tariffs, $from, $to);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $pdf->Output('Abrechnung.pdf', 'S');
|
return $pdf->Output('Abrechnung.pdf', 'S');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function BuildUserInvoice($pdf, $user, $power, $water, $tariffs, $from, $to)
|
private function BuildUserInvoice($pdf, $user, $power, $water, $tariffs, $from, $to)
|
||||||
{
|
{
|
||||||
$logoData = $this->ReadPropertyString('Logo');
|
|
||||||
if ($logoData !== '') {
|
|
||||||
$img = base64_decode($logoData);
|
|
||||||
$pdf->Image('@' . $img, 15, 10, 40);
|
|
||||||
$pdf->Ln(25);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf->AddPage();
|
|
||||||
|
|
||||||
// Kopfbereich
|
// Kopfbereich
|
||||||
$html = "
|
$html = "
|
||||||
<h1 style='text-align:center; margin-bottom:0;'>Elektro- und Nebenkostenabrechnung</h1>
|
<h1 style='text-align:center; margin-bottom:0;'>Elektro- und Nebenkostenabrechnung</h1>
|
||||||
<hr>
|
<hr>
|
||||||
<table width='100%' style='font-size:10px; margin-top:5px;'>
|
<table width='100%' style='font-size:8px; margin-top:5px;'>
|
||||||
<tr>
|
<tr>
|
||||||
<td width='60%'>
|
<td width='60%'>
|
||||||
<strong>Zählpunkte:</strong><br>";
|
<strong>Zählpunkte:</strong><br>";
|
||||||
@@ -163,26 +177,27 @@ if ($logoData !== '') {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<p style='font-size:10px; margin-top:10px;'>
|
<p style='font-size:8px; margin-top:10px;'>
|
||||||
<strong>Abrechnungszeitraum:</strong> " . date('d.m.Y', $from) . " – " . date('d.m.Y', $to) . "
|
<strong>Abrechnungszeitraum:</strong> " . date('d.m.Y', $from) . " – " . date('d.m.Y', $to) . "
|
||||||
</p>
|
</p>
|
||||||
<br><hr>
|
<br><hr>
|
||||||
";
|
";
|
||||||
|
|
||||||
// ========================= Elektrizität =========================
|
// ========================= Elektrizität =========================
|
||||||
$html .= "<h2 style='margin-bottom:3px;'>Elektrizität</h2>";
|
$html .= "<h2 style='margin-bottom:3px; font-size:10px;'>Elektrizität</h2>";
|
||||||
|
|
||||||
$powerResult = $this->GetCalculatedPowerCosts($user['id']);
|
$powerResult = $this->GetCalculatedPowerCosts($user['id']);
|
||||||
$html .= $powerResult['html'];
|
$html .= $powerResult['html'];
|
||||||
$totalPower = $powerResult['sum'];
|
$totalPower = $powerResult['sum'];
|
||||||
|
|
||||||
// ========== Stromtarife anzeigen ==========
|
// Elektrizitätstarife anzeigen
|
||||||
$appliedTariffs = $this->CollectTariffsForUser($tariffs, ['Netztarif','Solartarif','Einspeisetarif']);
|
$appliedTariffs = $this->CollectTariffsForUser($tariffs, ['Netztarif', 'Solartarif', 'Einspeisetarif']);
|
||||||
if (!empty($appliedTariffs)) {
|
if (!empty($appliedTariffs)) {
|
||||||
$html .= "<p style='font-size:8px; margin-top:4px;'><strong>Angewendete Elektrizitätstarife:</strong></p><ul style='font-size:7px;'>";
|
$html .= "<p style='font-size:7px; margin-top:4px;'><strong>Angewendete Elektrizitätstarife:</strong></p>
|
||||||
|
<ul style='font-size:7px;'>";
|
||||||
foreach ($appliedTariffs as $t) {
|
foreach ($appliedTariffs as $t) {
|
||||||
$html .= "<li>"
|
$html .= "<li>"
|
||||||
. date('d.m.Y', $t['start']) . "–" . date('d.m.Y', $t['end'])
|
. date('d.m.Y', $t['start']) . " – " . date('d.m.Y', $t['end'])
|
||||||
. " — <strong>" . number_format($t['price'], 2) . " Rp/kWh</strong>"
|
. " — <strong>" . number_format($t['price'], 2) . " Rp/kWh</strong>"
|
||||||
. "</li>";
|
. "</li>";
|
||||||
}
|
}
|
||||||
@@ -190,7 +205,7 @@ if ($logoData !== '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ========================= Nebenkosten =========================
|
// ========================= Nebenkosten =========================
|
||||||
$html .= "<h2 style='margin-bottom:3px;'>Nebenkosten</h2>";
|
$html .= "<h2 style='margin-bottom:3px; font-size:10px;'>Nebenkosten</h2>";
|
||||||
|
|
||||||
$additionalResult = $this->CalculateAdditionalCosts($water, $tariffs, $user['id'], $from, $to);
|
$additionalResult = $this->CalculateAdditionalCosts($water, $tariffs, $user['id'], $from, $to);
|
||||||
$html .= $additionalResult['html'];
|
$html .= $additionalResult['html'];
|
||||||
@@ -199,13 +214,13 @@ if ($logoData !== '') {
|
|||||||
// ========================= Gesamttotal =========================
|
// ========================= Gesamttotal =========================
|
||||||
$grandTotal = $totalPower + $totalAdditional;
|
$grandTotal = $totalPower + $totalAdditional;
|
||||||
$html .= "
|
$html .= "
|
||||||
<h2 style='text-align:right; margin-top:10px;'>
|
<h2 style='text-align:right; margin-top:10px; font-size:11px;'>
|
||||||
Gesamttotal: <strong>" . number_format($grandTotal, 2) . " CHF</strong>
|
Gesamttotal: <strong>" . number_format($grandTotal, 2) . " CHF</strong>
|
||||||
</h2>
|
</h2>
|
||||||
";
|
";
|
||||||
|
|
||||||
$pdf->writeHTML($html, true, false, true, false, '');
|
$pdf->writeHTML($html, true, false, true, false, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== Stromkosten (15-Minuten, alle User) ======================
|
// ====================== Stromkosten (15-Minuten, alle User) ======================
|
||||||
|
|
||||||
@@ -346,7 +361,7 @@ if ($logoData !== '') {
|
|||||||
|
|
||||||
private function GetCalculatedPowerCosts($userId)
|
private function GetCalculatedPowerCosts($userId)
|
||||||
{
|
{
|
||||||
$html = "
|
$html = "
|
||||||
<table border='1' cellspacing='0' cellpadding='2' width='100%' style='font-size:6px;'>
|
<table border='1' cellspacing='0' cellpadding='2' width='100%' style='font-size:6px;'>
|
||||||
<tr style='background-color:#f0f0f0;'>
|
<tr style='background-color:#f0f0f0;'>
|
||||||
<th>Zähler</th>
|
<th>Zähler</th>
|
||||||
@@ -362,7 +377,6 @@ $html = "
|
|||||||
<th>Total CHF</th>
|
<th>Total CHF</th>
|
||||||
</tr>";
|
</tr>";
|
||||||
|
|
||||||
|
|
||||||
if (empty($this->powerCostCache) || !isset($this->powerCostCache[$userId])) {
|
if (empty($this->powerCostCache) || !isset($this->powerCostCache[$userId])) {
|
||||||
$html .= "<tr><td colspan='11' align='center'>Keine Stromzähler für diesen Benutzer</td></tr></table><br>";
|
$html .= "<tr><td colspan='11' align='center'>Keine Stromzähler für diesen Benutzer</td></tr></table><br>";
|
||||||
return ['html' => $html, 'sum' => 0.0];
|
return ['html' => $html, 'sum' => 0.0];
|
||||||
@@ -401,7 +415,7 @@ $html = "
|
|||||||
|
|
||||||
private function CalculateAdditionalCosts($waterMeters, $tariffs, $userId, $from, $to)
|
private function CalculateAdditionalCosts($waterMeters, $tariffs, $userId, $from, $to)
|
||||||
{
|
{
|
||||||
$html = "
|
$html = "
|
||||||
<table border='1' cellspacing='0' cellpadding='2' width='100%' style='font-size:6px;'>
|
<table border='1' cellspacing='0' cellpadding='2' width='100%' style='font-size:6px;'>
|
||||||
<tr style='background-color:#f0f0f0;'>
|
<tr style='background-color:#f0f0f0;'>
|
||||||
<th>Zähler</th>
|
<th>Zähler</th>
|
||||||
@@ -415,7 +429,6 @@ $html = "
|
|||||||
<th>Kosten CHF</th>
|
<th>Kosten CHF</th>
|
||||||
</tr>";
|
</tr>";
|
||||||
|
|
||||||
|
|
||||||
$total = 0.0;
|
$total = 0.0;
|
||||||
$usedTariffs = [];
|
$usedTariffs = [];
|
||||||
|
|
||||||
@@ -433,7 +446,6 @@ $html = "
|
|||||||
$html .= "<tr style='background-color:#f9f9f9; font-weight:bold;'>
|
$html .= "<tr style='background-color:#f9f9f9; font-weight:bold;'>
|
||||||
<td colspan='8' align='right'><b>Total Nebenkosten:</b></td>
|
<td colspan='8' align='right'><b>Total Nebenkosten:</b></td>
|
||||||
<td align='right'><b>" . number_format($total, 2) . " CHF</b></td>
|
<td align='right'><b>" . number_format($total, 2) . " CHF</b></td>
|
||||||
|
|
||||||
</tr></table><br>";
|
</tr></table><br>";
|
||||||
|
|
||||||
if (!empty($usedTariffs)) {
|
if (!empty($usedTariffs)) {
|
||||||
@@ -667,14 +679,17 @@ $html = "
|
|||||||
}
|
}
|
||||||
return end($cands);
|
return end($cands);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function CollectTariffsForUser($tariffs, $types)
|
private function CollectTariffsForUser($tariffs, $types)
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
$wanted = array_map('strtolower', $types);
|
$wanted = array_map('strtolower', $types);
|
||||||
|
|
||||||
foreach ($tariffs as $t) {
|
foreach ($tariffs as $t) {
|
||||||
$type = strtolower(trim($t['unit_type'] ?? ''));
|
$type = strtolower(trim($t['unit_type'] ?? ''));
|
||||||
if (!in_array($type, $wanted)) continue;
|
if (!in_array($type, $wanted, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$start = $this->toUnixTs($t['start'], false);
|
$start = $this->toUnixTs($t['start'], false);
|
||||||
$end = $this->toUnixTs($t['end'], true);
|
$end = $this->toUnixTs($t['end'], true);
|
||||||
@@ -687,7 +702,36 @@ $html = "
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function GetLogoFile()
|
||||||
|
{
|
||||||
|
$mediaID = (int)$this->ReadPropertyInteger('LogoMediaID');
|
||||||
|
if ($mediaID <= 0 || !IPS_MediaExists($mediaID)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$media = IPS_GetMedia($mediaID);
|
||||||
|
$ext = 'png';
|
||||||
|
if (!empty($media['MediaFile'])) {
|
||||||
|
$extFromFile = pathinfo($media['MediaFile'], PATHINFO_EXTENSION);
|
||||||
|
if ($extFromFile !== '') {
|
||||||
|
$ext = $extFromFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = IPS_GetKernelDir() . 'media/logo_' . $mediaID . '.' . $ext;
|
||||||
|
|
||||||
|
// Bild aus der Symcon-Media-Datenbank extrahieren
|
||||||
|
$raw = IPS_GetMediaContent($mediaID); // base64
|
||||||
|
$bin = base64_decode($raw);
|
||||||
|
if ($bin === false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($path, $bin);
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user