<?php
/**
* Verbrauchserfassung pro Mieter
* Version 2 – mit 4 festen Blöcken
* Prefixe:
* ehzg_* = Energie Heizung (kWh)
* eww_* = Energie Warmwasser (kWh)
* ww_* = Warmwasser (m3)
* kw_* = Kaltwasser (m3)
*
* Einsatz:
* - als eigenständige PHP-Datei auf dem Webserver
* - oder in WordPress über ein eigenes Seiten-Template / kleines Plugin
*
* Aktuell speichert diese Vorlage die Daten als JSON-Zeile in /tmp
* und zeigt zusätzlich ein sauberes Array für die spätere Weitergabe
* an Nextcloud Tables.
*/
$errors = [];
$success = false;
$payload = [];
function field(string $name, string $default = ''): string {
return isset($_POST[$name]) ? trim((string)$_POST[$name]) : $default;
}
function is_checked(string $name): bool {
return isset($_POST[$name]) && $_POST[$name] === '1';
}
function normalize_number(string $value): ?string {
$value = trim($value);
if ($value === '') {
return null;
}
$value = str_replace([' ', "\t"], '', $value);
$value = str_replace(',', '.', $value);
return is_numeric($value) ? $value : null;
}
function create_meldung_id(): string {
return 'MELD-' . date('Ymd-His') . '-' . substr(bin2hex(random_bytes(4)), 0, 8);
}
function build_block(string $prefix, string $unit): array {
return [
"{$prefix}_zaehlernummer" => field("{$prefix}_zaehlernummer"),
"{$prefix}_einheit" => $unit,
"{$prefix}_stand_alt" => normalize_number(field("{$prefix}_stand_alt")),
"{$prefix}_stand_neu" => normalize_number(field("{$prefix}_stand_neu")),
"{$prefix}_mieterwechsel" => is_checked("{$prefix}_mieterwechsel"),
"{$prefix}_auszug_datum" => field("{$prefix}_auszug_datum"),
"{$prefix}_auszug_stand_alt" => normalize_number(field("{$prefix}_auszug_stand_alt")),
"{$prefix}_auszug_stand_neu" => normalize_number(field("{$prefix}_auszug_stand_neu")),
"{$prefix}_einzug_datum" => field("{$prefix}_einzug_datum"),
"{$prefix}_einzug_stand_alt" => normalize_number(field("{$prefix}_einzug_stand_alt")),
"{$prefix}_einzug_stand_neu" => normalize_number(field("{$prefix}_einzug_stand_neu")),
];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$required = [
'objekt_name' => 'Objekt / Haus',
'we_einheit' => 'WE / Einheit',
'mietername' => 'Name Mieter',
'abrechnung_von' => 'Abrechnung von',
'abrechnung_bis' => 'Abrechnung bis',
'vermieter_name' => 'Name Vermieter',
'vermieter_email' => 'E-Mail Vermieter',
];
foreach ($required as $key => $label) {
if (field($key) === '') {
$errors[] = "Bitte Feld ausfüllen: {$label}";
}
}
if (field('vermieter_email') !== '' && !filter_var(field('vermieter_email'), FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Bitte eine gültige E-Mail-Adresse eingeben.';
}
$blockPrefixes = ['ehzg', 'eww', 'ww', 'kw'];
foreach ($blockPrefixes as $prefix) {
foreach (["{$prefix}_stand_alt", "{$prefix}_stand_neu", "{$prefix}_auszug_stand_alt", "{$prefix}_auszug_stand_neu", "{$prefix}_einzug_stand_alt", "{$prefix}_einzug_stand_neu"] as $numField) {
$raw = field($numField);
if ($raw !== '' && normalize_number($raw) === null) {
$errors[] = "Ungültige Zahl in Feld: {$numField}";
}
}
}
if (!$errors) {
$payload = [
'meldung_id' => create_meldung_id(),
'erfasst_am' => date('c'),
'status' => 'neu',
'quelle' => 'wp_formular',
'importiert_nach_calc' => false,
'import_datum' => null,
'objekt_name' => field('objekt_name'),
'strasse_hsnr' => field('strasse_hsnr'),
'plz_ort' => field('plz_ort'),
'we_einheit' => field('we_einheit'),
'mietername' => field('mietername'),
'abrechnung_von' => field('abrechnung_von'),
'abrechnung_bis' => field('abrechnung_bis'),
'vermieter_name' => field('vermieter_name'),
'vermieter_email' => field('vermieter_email'),
'bemerkungen' => field('bemerkungen'),
'pruefcode' => '',
];
$payload = array_merge(
$payload,
build_block('ehzg', 'kWh'),
build_block('eww', 'kWh'),
build_block('ww', 'm3'),
build_block('kw', 'm3')
);
$storageDir = __DIR__ . '/formdata';
if (!is_dir($storageDir)) {
@mkdir($storageDir, 0775, true);
}
$targetFile = $storageDir . '/verbrauchsmeldungen.jsonl';
$jsonLine = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($jsonLine === false || @file_put_contents($targetFile, $jsonLine . PHP_EOL, FILE_APPEND | LOCK_EX) === false) {
$errors[] = 'Die Daten konnten nicht gespeichert werden.';
} else {
$success = true;
$_POST = [];
}
}
}
function h(string $value): string {
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
function render_block(string $title, string $prefix, string $unit): void {
?>
<section class="block">
<h2><?php echo h($title); ?></h2>
<div class="grid two">
<label>Zählernummer
<input type="text" name="<?php echo h($prefix); ?>_zaehlernummer" value="<?php echo h(field("{$prefix}_zaehlernummer")); ?>">
</label>
<label>Einheit
<input type="text" value="<?php echo h($unit); ?>" readonly>
</label>
<label>Stand alt
<input type="text" name="<?php echo h($prefix); ?>_stand_alt" value="<?php echo h(field("{$prefix}_stand_alt")); ?>" placeholder="z. B. 1234,56">
</label>
<label>Stand neu
<input type="text" name="<?php echo h($prefix); ?>_stand_neu" value="<?php echo h(field("{$prefix}_stand_neu")); ?>" placeholder="z. B. 1288,90">
</label>
</div>
<label class="checkbox-row">
<input type="checkbox" name="<?php echo h($prefix); ?>_mieterwechsel" value="1" <?php echo is_checked("{$prefix}_mieterwechsel") ? 'checked' : ''; ?>>
Mieterwechsel in diesem Zeitraum
</label>
<div class="mieterwechsel-box">
<h3>Bei Mieterwechsel</h3>
<div class="grid two">
<label>Datum Auszug
<input type="date" name="<?php echo h($prefix); ?>_auszug_datum" value="<?php echo h(field("{$prefix}_auszug_datum")); ?>">
</label>
<div></div>
<label>Stand alt bei Auszug
<input type="text" name="<?php echo h($prefix); ?>_auszug_stand_alt" value="<?php echo h(field("{$prefix}_auszug_stand_alt")); ?>">
</label>
<label>Stand neu bei Auszug
<input type="text" name="<?php echo h($prefix); ?>_auszug_stand_neu" value="<?php echo h(field("{$prefix}_auszug_stand_neu")); ?>">
</label>
<label>Datum Einzug
<input type="date" name="<?php echo h($prefix); ?>_einzug_datum" value="<?php echo h(field("{$prefix}_einzug_datum")); ?>">
</label>
<div></div>
<label>Stand alt bei Einzug
<input type="text" name="<?php echo h($prefix); ?>_einzug_stand_alt" value="<?php echo h(field("{$prefix}_einzug_stand_alt")); ?>">
</label>
<label>Stand neu bei Einzug
<input type="text" name="<?php echo h($prefix); ?>_einzug_stand_neu" value="<?php echo h(field("{$prefix}_einzug_stand_neu")); ?>">
</label>
</div>
</div>
</section>
<?php
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Verbrauchserfassung pro Mieter</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background: #f5f5f5;
color: #222;
}
.wrap {
max-width: 980px;
margin: 24px auto;
background: #fff;
padding: 24px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
h1 { margin-top: 0; }
h2 {
margin-top: 0;
background: #eef4ff;
padding: 10px 12px;
border-radius: 8px;
font-size: 20px;
}
h3 {
margin-top: 0;
font-size: 16px;
}
.hint {
background: #fff8d8;
border-left: 4px solid #d0ad00;
padding: 12px;
margin-bottom: 20px;
border-radius: 6px;
}
.error {
background: #fde7e7;
border-left: 4px solid #c9302c;
padding: 12px;
margin-bottom: 20px;
border-radius: 6px;
}
.success {
background: #e7f7ea;
border-left: 4px solid #2e8b57;
padding: 12px;
margin-bottom: 20px;
border-radius: 6px;
}
.block {
margin: 24px 0;
padding: 18px;
border: 1px solid #ddd;
border-radius: 10px;
}
.grid {
display: grid;
gap: 14px;
}
.grid.two {
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
label {
display: flex;
flex-direction: column;
gap: 6px;
font-weight: bold;
font-size: 14px;
}
input, textarea, select {
padding: 10px;
border: 1px solid #bbb;
border-radius: 8px;
font-size: 14px;
font-family: inherit;
}
textarea {
min-height: 100px;
resize: vertical;
}
.checkbox-row {
display: flex;
align-items: center;
gap: 10px;
margin: 14px 0;
font-weight: normal;
}
.checkbox-row input {
width: auto;
}
.mieterwechsel-box {
background: #fafafa;
border: 1px dashed #ccc;
border-radius: 8px;
padding: 14px;
}
.actions {
margin-top: 24px;
}
button {
background: #1f5fbf;
color: white;
border: none;
border-radius: 8px;
padding: 12px 18px;
font-size: 15px;
cursor: pointer;
}
button:hover { opacity: 0.92; }
pre {
background: #111;
color: #f2f2f2;
padding: 14px;
overflow: auto;
border-radius: 8px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="wrap">
<h1>Verbrauchserfassung pro Mieter</h1>
<div class="hint">
Bitte alle Felder möglichst vollständig ausfüllen. Zahlen bitte ohne Einheit eingeben, also z. B. <strong>52,00</strong> oder <strong>13185,00</strong>.
</div>
<?php if ($errors): ?>
<div class="error">
<strong>Bitte prüfen:</strong>
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo h($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<strong>Vielen Dank.</strong> Die Daten wurden erfolgreich gespeichert.
</div>
<details>
<summary>Gespeicherte Daten anzeigen</summary>
<pre><?php echo h(json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); ?></pre>
</details>
<?php endif; ?>
<form method="post">
<section class="block">
<h2>1. Stammdaten</h2>
<div class="grid two">
<label>Objekt / Haus *
<input type="text" name="objekt_name" value="<?php echo h(field('objekt_name')); ?>" required>
</label>
<label>Straße + Hausnummer
<input type="text" name="strasse_hsnr" value="<?php echo h(field('strasse_hsnr')); ?>">
</label>
<label>PLZ / Ort
<input type="text" name="plz_ort" value="<?php echo h(field('plz_ort')); ?>">
</label>
<label>WE / Einheit *
<input type="text" name="we_einheit" value="<?php echo h(field('we_einheit')); ?>" required>
</label>
<label>Name Mieter *
<input type="text" name="mietername" value="<?php echo h(field('mietername')); ?>" required>
</label>
<label>Abrechnung von *
<input type="date" name="abrechnung_von" value="<?php echo h(field('abrechnung_von')); ?>" required>
</label>
<label>Abrechnung bis *
<input type="date" name="abrechnung_bis" value="<?php echo h(field('abrechnung_bis')); ?>" required>
</label>
<label>Name Vermieter *
<input type="text" name="vermieter_name" value="<?php echo h(field('vermieter_name')); ?>" required>
</label>
<label>E-Mail Vermieter *
<input type="email" name="vermieter_email" value="<?php echo h(field('vermieter_email')); ?>" required>
</label>
</div>
<label style="margin-top: 14px;">Bemerkungen
<textarea name="bemerkungen"><?php echo h(field('bemerkungen')); ?></textarea>
</label>
</section>
<?php render_block('2. Energie Heizung (kWh)', 'ehzg', 'kWh'); ?>
<?php render_block('3. Energie für die Aufbereitung von Warmwasser (kWh)', 'eww', 'kWh'); ?>
<?php render_block('4. Warmwasser (m3)', 'ww', 'm3'); ?>
<?php render_block('5. Kaltwasser (m3)', 'kw', 'm3'); ?>
<div class="actions">
<button type="submit">Daten absenden</button>
</div>
</form>
</div>
</body>
</html>