no message

This commit is contained in:
2026-06-28 13:26:59 +02:00
parent 5446da8c68
commit 37f8ddffd6
+629 -11
View File
@@ -70,6 +70,8 @@ class Abrechnung extends IPSModule
$this->RegisterVariableFloat('VisuTariffPrice', 'Tarif Rp/Einheit', 'BELEVO.TariffPrice', 14);
$this->RegisterVariableString('VisuTariffStatus', 'Tarif Status', '', 15);
$this->RegisterVariableString('VisuTariffPayload', 'Tarif Payload', '', 16);
$this->RegisterVariableString('VisuUserOverview', 'Benutzer bearbeiten', '~HTMLBox', 20);
$this->RegisterVariableString('VisuUserStatus', 'Benutzer Status', '', 21);
$this->EnableAction('FromDate');
$this->EnableAction('ToDate');
$this->EnableAction('VisuTariffType');
@@ -84,6 +86,7 @@ class Abrechnung extends IPSModule
"<?php IPS_RequestAction(" . $this->InstanceID . ", 'StartBilling', ''); ?>"
);
$this->EnsureVisuTariffObjects();
$this->EnsureVisuUserObjects();
$this->RegisterMediaDocument('InvoicePDF', 'Letzte Rechnung', 'pdf');
}
@@ -93,8 +96,10 @@ class Abrechnung extends IPSModule
$this->RegisterTariffVariableProfiles();
$this->RegisterTariffWebhook();
$this->EnsureVisuTariffObjects();
$this->EnsureVisuUserObjects();
$this->InitializeVisuTariffDefaults();
$this->UpdateTariffOverview();
$this->UpdateUserOverview();
}
private function RegisterTariffWebhook()
@@ -162,6 +167,13 @@ class Abrechnung extends IPSModule
}
}
private function EnsureVisuUserObjects()
{
$this->RegisterVariableString('VisuUserOverview', 'Benutzer bearbeiten', '~HTMLBox', 20);
$this->RegisterVariableString('VisuUserStatus', 'Benutzer Status', '', 21);
$this->HideObjectByIdent('VisuUserStatus');
}
private function HideObjectByIdent($Ident)
{
$id = @IPS_GetObjectIDByIdent($Ident, $this->InstanceID);
@@ -411,6 +423,7 @@ class Abrechnung extends IPSModule
.belevo-tariffs .status{margin-left:8px;color:#4b5563}
</style>
<form method='post' action='" . $this->h($webhookPath) . "' target='belevo_tariff_save_frame'>
<input type='hidden' name='editor' value='tariffs'>
<input type='hidden' name='payload' value=''>
<table>
<thead>
@@ -573,6 +586,591 @@ form.onsubmit=function(){
return $this->SaveTariffTableFromPayload(json_encode($rows));
}
private function ReadUsers()
{
$users = json_decode($this->ReadPropertyString('Users'), true);
return is_array($users) ? array_values($users) : [];
}
private function ReadPowerMeters()
{
$meters = json_decode($this->ReadPropertyString('PowerMeters'), true);
return is_array($meters) ? array_values($meters) : [];
}
private function ReadWaterMeters()
{
$meters = json_decode($this->ReadPropertyString('WaterMeters'), true);
return is_array($meters) ? array_values($meters) : [];
}
private function WriteUsersAndMeterAssignments(array $users, array $powerMeters, array $waterMeters)
{
IPS_SetProperty($this->InstanceID, 'Users', json_encode(array_values($users), JSON_UNESCAPED_UNICODE));
IPS_SetProperty($this->InstanceID, 'PowerMeters', json_encode(array_values($powerMeters), JSON_UNESCAPED_UNICODE));
IPS_SetProperty($this->InstanceID, 'WaterMeters', json_encode(array_values($waterMeters), JSON_UNESCAPED_UNICODE));
IPS_ApplyChanges($this->InstanceID);
$this->UpdateUserOverview();
}
private function UpdateUserOverview()
{
$overviewID = @IPS_GetObjectIDByIdent('VisuUserOverview', $this->InstanceID);
if ($overviewID === false) {
return;
}
$users = $this->ReadUsers();
$powerMeters = $this->ReadPowerMeters();
$waterMeters = $this->ReadWaterMeters();
$rows = '';
foreach ($users as $index => $user) {
$rows .= $this->BuildUserEditorRow((string)$index, is_array($user) ? $user : [], $powerMeters, $waterMeters);
}
if ($rows === '') {
$rows = $this->BuildUserEditorRow('0', [], $powerMeters, $waterMeters);
}
$webhookPath = $this->GetTariffWebhookPath();
$statusID = @IPS_GetObjectIDByIdent('VisuUserStatus', $this->InstanceID);
$status = $statusID !== false ? $this->h(@GetValue($statusID)) : '';
$template = $this->BuildUserEditorRow('__KEY__', [], $powerMeters, $waterMeters);
$html = "
<div class='belevo-users'>
<style>
.belevo-users{font-family:Arial,Helvetica,sans-serif;font-size:13px;color:#202124;max-width:1220px;margin-top:18px}
.belevo-users table{width:100%;border-collapse:collapse;background:#fff}
.belevo-users th{background:#f3f4f6;border:1px solid #d6d9de;text-align:left;padding:7px;font-weight:700}
.belevo-users td{border:1px solid #e0e2e6;padding:5px;vertical-align:top}
.belevo-users input,.belevo-users select{width:100%;box-sizing:border-box;border:1px solid #c7cbd1;border-radius:3px;padding:5px;font:inherit;background:#fff}
.belevo-users option:disabled{color:#9aa0a6;background:#f1f3f4}
.belevo-users .meter-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.belevo-users .meter-tag{display:inline-flex;align-items:center;gap:5px;border:1px solid #c7cbd1;background:#f8f9fa;border-radius:3px;padding:3px 6px;max-width:100%}
.belevo-users .meter-tag span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.belevo-users .meter-tag button{border:0;background:transparent;color:#9b1c1c;padding:0 2px;font-weight:700}
.belevo-users .actions{display:flex;gap:8px;margin-top:10px;align-items:center}
.belevo-users button{border:1px solid #9aa0a6;background:#f8f9fa;border-radius:3px;padding:6px 10px;font:inherit;cursor:pointer}
.belevo-users button.primary{background:#1f4e79;border-color:#1f4e79;color:#fff;font-weight:700}
.belevo-users button.danger{color:#9b1c1c;border-color:#d7a6a6;background:#fff5f5}
.belevo-users .status{margin-left:8px;color:#4b5563}
</style>
<form method='post' action='" . $this->h($webhookPath) . "' target='belevo_user_save_frame'>
<input type='hidden' name='editor' value='users'>
<table>
<thead>
<tr>
<th style='width:18%'>Name</th>
<th style='width:18%'>Adresse</th>
<th style='width:18%'>Ort</th>
<th style='width:19%'>Stromzaehler</th>
<th style='width:19%'>Nebenzaehler</th>
<th style='width:8%'>Aktion</th>
</tr>
</thead>
<tbody>" . $rows . "</tbody>
</table>
<div class='actions'>
<button type='button' data-action='add-user'>Zeile hinzufuegen</button>
<button type='submit' class='primary'>Benutzer speichern</button>
<span class='status'>" . $status . "</span>
</div>
</form>
<iframe name='belevo_user_save_frame' style='display:none;width:0;height:0;border:0'></iframe>
<template data-user-row-template>" . $template . "</template>
<script>
(function(){
var root=document.currentScript.closest('.belevo-users');
if(!root||root.dataset.bound==='1'){return;}
root.dataset.bound='1';
var tbody=root.querySelector('tbody');
var status=root.querySelector('.status');
var counter=0;
window.addEventListener('message',function(event){
if(event&&event.data&&event.data.type==='belevoUserSave'){
status.textContent=event.data.message||'Gespeichert.';
}
});
function bindDelete(row){
var btn=row.querySelector('[data-action=delete-user]');
if(btn){btn.onclick=function(){row.parentNode.removeChild(row);};}
}
function selectedByKind(){
var selected={power:{},water:{}};
Array.prototype.forEach.call(root.querySelectorAll('.meter-picker'),function(picker){
var kind=picker.getAttribute('data-kind');
Array.prototype.forEach.call(picker.querySelectorAll('.meter-tag'),function(tag){
var value=tag.getAttribute('data-value');
if(value!==''){selected[kind][value]=true;}
});
});
return selected;
}
function refreshPickers(){
var selected=selectedByKind();
Array.prototype.forEach.call(root.querySelectorAll('.meter-picker'),function(picker){
var kind=picker.getAttribute('data-kind');
var select=picker.querySelector('select[data-action=add-meter]');
Array.prototype.forEach.call(select.options,function(option){
if(option.value===''){return;}
var base=option.getAttribute('data-label')||option.textContent;
var assigned=!!selected[kind][option.value];
option.disabled=assigned;
option.textContent=assigned?base+' (vergeben)':base;
});
select.value='';
});
}
function addMeterTag(picker,value,label){
if(value===''){return;}
if(picker.querySelector('.meter-tag[data-value=\"'+value+'\"]')){return;}
var tag=document.createElement('span');
tag.className='meter-tag';
tag.setAttribute('data-value',value);
var input=document.createElement('input');
input.type='hidden';
input.name=picker.getAttribute('data-field-name');
input.value=value;
var text=document.createElement('span');
text.textContent=label;
var remove=document.createElement('button');
remove.type='button';
remove.setAttribute('data-action','remove-meter');
remove.textContent='x';
tag.appendChild(input);
tag.appendChild(text);
tag.appendChild(remove);
picker.querySelector('.meter-tags').appendChild(tag);
refreshPickers();
}
Array.prototype.forEach.call(tbody.querySelectorAll('tr'),bindDelete);
root.querySelector('[data-action=add-user]').onclick=function(){
var key='new_'+Date.now()+'_'+(counter++);
var tpl=root.querySelector('template[data-user-row-template]').innerHTML.replace(/__KEY__/g,key);
var temp=document.createElement('tbody');
temp.innerHTML=tpl;
var row=temp.querySelector('tr');
tbody.appendChild(row);
bindDelete(row);
refreshPickers();
};
root.addEventListener('change',function(event){
var select=event.target;
if(!select||select.getAttribute('data-action')!=='add-meter'){return;}
var option=select.options[select.selectedIndex];
if(!option||!option.value){return;}
addMeterTag(select.closest('.meter-picker'),option.value,option.getAttribute('data-label')||option.textContent);
});
root.addEventListener('click',function(event){
var btn=event.target;
if(!btn||btn.getAttribute('data-action')!=='remove-meter'){return;}
var tag=btn.closest('.meter-tag');
if(tag&&tag.parentNode){tag.parentNode.removeChild(tag);}
refreshPickers();
});
root.querySelector('form').onsubmit=function(){
status.textContent='Speichern gesendet.';
return true;
};
refreshPickers();
})();
</script>
</div>";
SetValue($overviewID, $html);
}
private function BuildUserEditorRow($rowKey, array $user, array $powerMeters, array $waterMeters)
{
$userId = trim((string)($user['id'] ?? ''));
$powerSelected = $this->GetMeterIndexesForUser($powerMeters, $userId);
$waterSelected = $this->GetMeterIndexesForUser($waterMeters, $userId);
return '<tr>'
. '<td><input type="hidden" name="user_id[]" value="' . $this->h($userId) . '"><input type="hidden" name="row_key[]" value="' . $this->h($rowKey) . '"><input name="user_name[]" value="' . $this->h($user['name'] ?? '') . '"></td>'
. '<td><input name="user_address[]" value="' . $this->h($user['address'] ?? '') . '"></td>'
. '<td><input name="user_city[]" value="' . $this->h($user['city'] ?? '') . '"></td>'
. '<td>' . $this->BuildMeterPicker('power', 'power_assign', $rowKey, $powerMeters, $powerSelected) . '</td>'
. '<td>' . $this->BuildMeterPicker('water', 'water_assign', $rowKey, $waterMeters, $waterSelected) . '</td>'
. '<td><button type="button" class="danger" data-action="delete-user">Loeschen</button></td>'
. '</tr>';
}
private function GetMeterIndexesForUser(array $meters, $userId)
{
if ($userId === '') {
return [];
}
$indexes = [];
foreach ($meters as $index => $meter) {
if ((string)($meter['user_id'] ?? '') === (string)$userId) {
$indexes[] = (string)$index;
}
}
return $indexes;
}
private function BuildMeterPicker($kind, $fieldName, $rowKey, array $meters, array $selectedIndexes)
{
$inputName = $fieldName . '[' . $rowKey . '][]';
$tags = '';
foreach ($selectedIndexes as $selectedIndex) {
if (!array_key_exists((int)$selectedIndex, $meters)) {
continue;
}
$label = $this->GetMeterLabel($meters[(int)$selectedIndex], (int)$selectedIndex);
$tags .= '<span class="meter-tag" data-value="' . $this->h($selectedIndex) . '">'
. '<input type="hidden" name="' . $this->h($inputName) . '" value="' . $this->h($selectedIndex) . '">'
. '<span>' . $this->h($label) . '</span>'
. '<button type="button" data-action="remove-meter">x</button>'
. '</span>';
}
return '<div class="meter-picker" data-kind="' . $this->h($kind) . '" data-field-name="' . $this->h($inputName) . '">'
. '<select data-action="add-meter">'
. '<option value="">Zaehler waehlen...</option>'
. $this->BuildMeterOptions($meters)
. '</select>'
. '<div class="meter-tags">' . $tags . '</div>'
. '</div>';
}
private function BuildMeterOptions(array $meters)
{
if (empty($meters)) {
return '<option value="" disabled>Keine Zaehler</option>';
}
$options = '';
foreach ($meters as $index => $meter) {
$key = (string)$index;
$label = $this->GetMeterLabel($meter, $index);
$assigned = trim((string)($meter['user_id'] ?? '')) !== '';
$options .= '<option value="' . $this->h($key) . '" data-label="' . $this->h($label) . '"' . ($assigned ? ' disabled' : '') . '>' . $this->h($assigned ? $label . ' (vergeben)' : $label) . '</option>';
}
return $options;
}
private function GetMeterLabel(array $meter, $index)
{
$id = trim((string)($meter['id'] ?? ''));
$name = trim((string)($meter['name'] ?? ''));
$type = trim((string)($meter['meter_type'] ?? ''));
if ($name === '' && $id === '') {
$label = 'Zaehler ' . ((int)$index + 1);
} elseif ($name === '') {
$label = $id;
} else {
$label = $name;
if ($id !== '' && $id !== $name) {
$label .= ' [' . $id . ']';
}
}
if ($type !== '') {
$label .= ' - ' . $type;
}
return $label;
}
private function SaveUsersTableFromPost(array $post)
{
$ids = $post['user_id'] ?? [];
$names = $post['user_name'] ?? [];
$addresses = $post['user_address'] ?? [];
$cities = $post['user_city'] ?? [];
$rowKeys = $post['row_key'] ?? [];
$powerAssign = $post['power_assign'] ?? [];
$waterAssign = $post['water_assign'] ?? [];
if (!is_array($ids) || !is_array($names) || !is_array($addresses) || !is_array($cities) || !is_array($rowKeys)) {
throw new Exception('Ungueltige Benutzerwerte.');
}
if (!is_array($powerAssign)) {
$powerAssign = [];
}
if (!is_array($waterAssign)) {
$waterAssign = [];
}
$existingUsers = [];
foreach ($this->ReadUsers() as $existingUser) {
if (!is_array($existingUser)) {
continue;
}
$existingId = (string)($existingUser['id'] ?? '');
if ($existingId !== '') {
$existingUsers[$existingId] = $existingUser;
}
}
$powerMeters = $this->ReadPowerMeters();
$waterMeters = $this->ReadWaterMeters();
foreach ($powerMeters as &$powerMeter) {
unset($powerMeter['user_id']);
}
unset($powerMeter);
foreach ($waterMeters as &$waterMeter) {
unset($waterMeter['user_id']);
}
unset($waterMeter);
$users = [];
$seenUsers = [];
foreach (array_keys($existingUsers) as $existingId) {
$seenUsers[(string)$existingId] = false;
}
$assignedPower = [];
$assignedWater = [];
$count = max(count($ids), count($names), count($addresses), count($cities), count($rowKeys));
for ($i = 0; $i < $count; $i++) {
$rowKey = (string)($rowKeys[$i] ?? $i);
$id = trim((string)($ids[$i] ?? ''));
$name = trim((string)($names[$i] ?? ''));
$address = trim((string)($addresses[$i] ?? ''));
$city = trim((string)($cities[$i] ?? ''));
$selectedPower = $this->NormalizeMeterSelection($powerAssign[$rowKey] ?? []);
$selectedWater = $this->NormalizeMeterSelection($waterAssign[$rowKey] ?? []);
if ($id === '' && $name === '' && $address === '' && $city === '' && empty($selectedPower) && empty($selectedWater)) {
continue;
}
if ($id === '') {
$id = $this->GenerateUniqueUserId($seenUsers);
}
if (isset($seenUsers[$id]) && $seenUsers[$id] === true) {
throw new Exception('Benutzer-ID doppelt: ' . $id);
}
$seenUsers[$id] = true;
$user = $existingUsers[$id] ?? [];
$user['id'] = $id;
$user['name'] = $name;
$user['address'] = $address;
$user['city'] = $city;
$users[] = $user;
foreach ($selectedPower as $meterIndex) {
if (!array_key_exists($meterIndex, $powerMeters)) {
throw new Exception('Stromzaehler nicht gefunden.');
}
if (isset($assignedPower[$meterIndex])) {
throw new Exception('Stromzaehler mehrfach zugewiesen: ' . $this->GetMeterLabel($powerMeters[$meterIndex], $meterIndex));
}
$powerMeters[$meterIndex]['user_id'] = $id;
$assignedPower[$meterIndex] = true;
}
foreach ($selectedWater as $meterIndex) {
if (!array_key_exists($meterIndex, $waterMeters)) {
throw new Exception('Nebenzaehler nicht gefunden.');
}
if (isset($assignedWater[$meterIndex])) {
throw new Exception('Nebenzaehler mehrfach zugewiesen: ' . $this->GetMeterLabel($waterMeters[$meterIndex], $meterIndex));
}
$waterMeters[$meterIndex]['user_id'] = $id;
$assignedWater[$meterIndex] = true;
}
}
$this->WriteUsersAndMeterAssignments($users, $powerMeters, $waterMeters);
return count($users) . ' Benutzer gespeichert.';
}
private function GenerateUniqueUserId(array $usedIds)
{
for ($i = 0; $i < 100; $i++) {
$id = (string)random_int(100000, 999999999);
if (!isset($usedIds[$id])) {
return $id;
}
}
do {
$id = (string)time() . (string)random_int(1000, 9999);
} while (isset($usedIds[$id]));
return $id;
}
private function NormalizeMeterSelection($selection)
{
if (!is_array($selection)) {
$selection = [$selection];
}
$result = [];
foreach ($selection as $value) {
$value = trim((string)$value);
if ($value === '') {
continue;
}
if (!ctype_digit($value)) {
throw new Exception('Ungueltige Zaehlerauswahl.');
}
$result[] = (int)$value;
}
return array_values(array_unique($result));
}
private function ValidateBillingConfiguration(array $users, array $powerMeters, array $waterMeters, array $tariffs, $from, $to)
{
$errors = [];
$from = (int)$from;
$to = (int)$to;
if ($from <= 0 || $to <= 0 || $to <= $from) {
$errors[] = 'Abrechnungszeitraum ist ungueltig.';
}
$userIds = [];
foreach ($users as $index => $user) {
if (!is_array($user)) {
continue;
}
$id = trim((string)($user['id'] ?? ''));
if ($id === '') {
$errors[] = 'Benutzer ohne interne ID gefunden.';
continue;
}
if (isset($userIds[$id])) {
$errors[] = 'Benutzer-ID doppelt: ' . $id;
}
$userIds[$id] = true;
}
if (empty($userIds)) {
$errors[] = 'Keine Benutzer konfiguriert.';
}
$hasAnyMeter = false;
$hasPowerConsumption = false;
$hasPowerFeed = false;
foreach ($powerMeters as $index => $meter) {
if (!is_array($meter)) {
continue;
}
$hasAnyMeter = true;
$userId = trim((string)($meter['user_id'] ?? ''));
if ($userId === '' || !isset($userIds[$userId])) {
$errors[] = 'Stromzaehler nicht zugewiesen: ' . $this->GetMeterLabel($meter, $index);
}
if (!empty($meter['var_consumption'])) {
$hasPowerConsumption = true;
}
if (!empty($meter['var_feed'])) {
$hasPowerFeed = true;
}
}
$requiredAdditionalTariffs = [];
foreach ($waterMeters as $index => $meter) {
if (!is_array($meter)) {
continue;
}
$hasAnyMeter = true;
$userId = trim((string)($meter['user_id'] ?? ''));
if ($userId === '' || !isset($userIds[$userId])) {
$errors[] = 'Nebenzaehler nicht zugewiesen: ' . $this->GetMeterLabel($meter, $index);
}
$type = trim((string)($meter['meter_type'] ?? 'Warmwasser'));
if ($type === '') {
$type = 'Warmwasser';
}
$requiredAdditionalTariffs[$type] = true;
}
if (!$hasAnyMeter) {
$errors[] = 'Keine Zaehler konfiguriert.';
}
if ($from > 0 && $to > $from) {
if ($hasPowerConsumption || $hasPowerFeed) {
$this->RequireTariffCoverage($tariffs, 'Netztarif', $from, $to, $errors);
}
if ($hasPowerFeed) {
$this->RequireTariffCoverage($tariffs, 'Solartarif', $from, $to, $errors);
$this->RequireTariffCoverage($tariffs, 'Einspeisetarif', $from, $to, $errors);
}
foreach (array_keys($requiredAdditionalTariffs) as $type) {
$this->RequireTariffCoverage($tariffs, $type, $from, $to, $errors);
}
}
if (!empty($errors)) {
throw new Exception(implode(' ', array_values(array_unique($errors))));
}
}
private function RequireTariffCoverage(array $tariffs, $type, $from, $to, array &$errors)
{
$gap = $this->GetTariffCoverageGap($tariffs, $type, (int)$from, (int)$to);
if ($gap === null) {
return;
}
$errors[] = 'Tarif fehlt durchgehend: ' . $type . ' (' . date('d.m.Y H:i', $gap[0]) . ' - ' . date('d.m.Y H:i', $gap[1]) . ').';
}
private function GetTariffCoverageGap(array $tariffs, $type, $from, $to)
{
$periodStart = (int)$from;
$periodEnd = (int)$to;
if ($periodEnd > $periodStart) {
$periodEnd--;
}
if ($periodStart <= 0 || $periodEnd < $periodStart) {
return [$periodStart, $periodEnd];
}
$intervals = [];
foreach ($tariffs as $tariff) {
if (!is_array($tariff)) {
continue;
}
if (strtolower(trim((string)($tariff['unit_type'] ?? ''))) !== strtolower(trim((string)$type))) {
continue;
}
$start = $this->toUnixTs($tariff['start'] ?? 0, false);
$end = $this->toUnixTs($tariff['end'] ?? 0, true);
if ($start === null || $end === null || $end < $periodStart || $start > $periodEnd) {
continue;
}
$intervals[] = [
max($periodStart, (int)$start),
min($periodEnd, (int)$end)
];
}
usort($intervals, function ($a, $b) {
return $a[0] <=> $b[0];
});
$cursor = $periodStart;
foreach ($intervals as $interval) {
if ($interval[0] > $cursor) {
return [$cursor, min($periodEnd, $interval[0] - 1)];
}
if ($interval[1] >= $cursor) {
$cursor = $interval[1] + 1;
}
if ($cursor > $periodEnd) {
return null;
}
}
return [$cursor, $periodEnd];
}
private function FormatDateInput($timestamp)
{
return $timestamp ? date('Y-m-d', (int)$timestamp) : '';
@@ -655,6 +1253,7 @@ form.onsubmit=function(){
try {
$pdfContent = $this->GenerateInvoices();
if (!$pdfContent) {
SetValue($this->GetIDForIdent('LastResult'), 'Abrechnung Fehler');
echo 'Abrechnung Fehler';
return;
}
@@ -664,8 +1263,9 @@ form.onsubmit=function(){
SetValue($this->GetIDForIdent('LastResult'), 'Abrechnung erfolgreich erstellt');
echo 'Abrechnung erfolgreich erstellt';
} catch (Throwable $e) {
SetValue($this->GetIDForIdent('LastResult'), 'Abrechnung Fehler');
echo 'Abrechnung Fehler: ' . $e->getMessage();
$message = 'Abrechnung Fehler: ' . $e->getMessage();
SetValue($this->GetIDForIdent('LastResult'), $message);
echo $message;
}
break;
}
@@ -674,22 +1274,38 @@ form.onsubmit=function(){
public function ProcessHookData()
{
$message = '';
$postMessageType = 'belevoTariffSave';
try {
$payload = $_POST['payload'] ?? '';
if (trim((string)$payload) !== '') {
$message = $this->SaveTariffTableFromPayload($payload);
$editor = (string)($_POST['editor'] ?? 'tariffs');
if ($editor === 'users') {
$postMessageType = 'belevoUserSave';
$message = $this->SaveUsersTableFromPost($_POST);
SetValue($this->GetIDForIdent('VisuUserStatus'), $message);
$this->UpdateUserOverview();
} else {
$message = $this->SaveTariffTableFromPost($_POST);
$payload = $_POST['payload'] ?? '';
if (trim((string)$payload) !== '') {
$message = $this->SaveTariffTableFromPayload($payload);
} else {
$message = $this->SaveTariffTableFromPost($_POST);
}
SetValue($this->GetIDForIdent('VisuTariffStatus'), $message);
$this->UpdateTariffOverview();
}
SetValue($this->GetIDForIdent('VisuTariffStatus'), $message);
$this->UpdateTariffOverview();
} catch (Throwable $e) {
$message = 'Fehler beim Speichern der Tarifliste: ' . $e->getMessage();
SetValue($this->GetIDForIdent('VisuTariffStatus'), $message);
if ($postMessageType === 'belevoUserSave') {
$message = 'Fehler beim Speichern der Benutzerliste: ' . $e->getMessage();
SetValue($this->GetIDForIdent('VisuUserStatus'), $message);
$this->UpdateUserOverview();
} else {
$message = 'Fehler beim Speichern der Tarifliste: ' . $e->getMessage();
SetValue($this->GetIDForIdent('VisuTariffStatus'), $message);
$this->UpdateTariffOverview();
}
}
header('Content-Type: text/html; charset=utf-8');
echo '<!doctype html><html><body><script>try{parent.postMessage({type:"belevoTariffSave",message:' . json_encode($message) . '}, "*");}catch(e){}</script>' . $this->h($message) . '</body></html>';
echo '<!doctype html><html><body><script>try{parent.postMessage({type:' . json_encode($postMessageType) . ',message:' . json_encode($message) . '}, "*");}catch(e){}</script>' . $this->h($message) . '</body></html>';
}
// ====================== PDF-Erstellung ======================
@@ -709,6 +1325,8 @@ public function GenerateInvoices()
$water = is_array($water) ? $water : [];
$tariffs = is_array($tariffs) ? $tariffs : [];
$this->ValidateBillingConfiguration($users, $power, $water, $tariffs, (int)$from, (int)$to);
if (!class_exists('TCPDF')) {
return false;
}