- output_location (Räumlichkeit): Neues Textfeld am Abgang für Raum/Ort des Verbrauchers. DB-Migration, Backend (AJAX), Frontend (Website + PWA), Anzeige im Schaltplan (kursiv) und in PDF-Tabellen. - Verteilungs-Tabellen: Kundenansicht (A4, Nr/Verbraucher/Räumlichkeit) und Technikeransicht (A4, R.Klem/FI/Nr/Verbraucher/Räumlichkeit/Typ) im Leitungslaufplan-PDF. Gruppiert nach Feld/Reihe mit automatischem Seitenumbruch. - Bundled-Terminals Checkbox: Im Website-Abgang-Dialog (war vorher nur PWA). - PWA: Diverse Verbesserungen, Service Worker v12.4, Connection-Modal erweitert. - Typ-Flags: has_product auch für Gebäudetypen, Equipment-Typ Erweiterungen. - CLAUDE.md + Doku aktualisiert. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
359 lines
13 KiB
PHP
Executable file
359 lines
13 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* Admin page for Building Types (Gebäudetypen)
|
|
*/
|
|
|
|
// Load Dolibarr environment
|
|
$res = 0;
|
|
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
|
|
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
|
|
if (!$res) die("Include of main fails");
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
|
|
dol_include_once('/kundenkarte/lib/kundenkarte.lib.php');
|
|
dol_include_once('/kundenkarte/class/buildingtype.class.php');
|
|
|
|
// Load translation files
|
|
$langs->loadLangs(array('admin', 'kundenkarte@kundenkarte'));
|
|
|
|
// Security check
|
|
if (!$user->admin) {
|
|
accessforbidden();
|
|
}
|
|
|
|
$action = GETPOST('action', 'aZ09');
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$id = GETPOSTINT('id');
|
|
$levelFilter = GETPOST('level_filter', 'alpha');
|
|
|
|
$buildingType = new BuildingType($db);
|
|
$error = 0;
|
|
|
|
// Actions
|
|
if ($action == 'add' && $user->admin) {
|
|
$buildingType->ref = GETPOST('ref', 'alphanohtml');
|
|
$buildingType->label = GETPOST('label', 'alphanohtml');
|
|
$buildingType->label_short = GETPOST('label_short', 'alphanohtml');
|
|
$buildingType->description = GETPOST('description', 'restricthtml');
|
|
$buildingType->fk_parent = GETPOSTINT('fk_parent');
|
|
$buildingType->level_type = GETPOST('level_type', 'alpha');
|
|
$buildingType->icon = GETPOST('icon', 'alphanohtml');
|
|
$buildingType->color = GETPOST('color', 'alphanohtml');
|
|
$buildingType->can_have_children = GETPOSTINT('can_have_children');
|
|
$buildingType->has_product = GETPOSTINT('has_product');
|
|
$buildingType->position = GETPOSTINT('position');
|
|
$buildingType->active = GETPOSTINT('active');
|
|
|
|
if (empty($buildingType->ref)) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesaliases('Ref')), null, 'errors');
|
|
$error++;
|
|
}
|
|
if (empty($buildingType->label)) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesaliases('Label')), null, 'errors');
|
|
$error++;
|
|
}
|
|
|
|
if (!$error) {
|
|
$result = $buildingType->create($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordCreatedSuccessfully'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF']);
|
|
exit;
|
|
} else {
|
|
setEventMessages($buildingType->error, $buildingType->errors, 'errors');
|
|
}
|
|
}
|
|
$action = 'create';
|
|
}
|
|
|
|
if ($action == 'update' && $user->admin) {
|
|
$result = $buildingType->fetch($id);
|
|
if ($result > 0) {
|
|
// Don't allow editing ref of system types
|
|
if (!$buildingType->is_system) {
|
|
$buildingType->ref = GETPOST('ref', 'alphanohtml');
|
|
}
|
|
$buildingType->label = GETPOST('label', 'alphanohtml');
|
|
$buildingType->label_short = GETPOST('label_short', 'alphanohtml');
|
|
$buildingType->description = GETPOST('description', 'restricthtml');
|
|
$buildingType->fk_parent = GETPOSTINT('fk_parent');
|
|
$buildingType->level_type = GETPOST('level_type', 'alpha');
|
|
$buildingType->icon = GETPOST('icon', 'alphanohtml');
|
|
$buildingType->color = GETPOST('color', 'alphanohtml');
|
|
$buildingType->can_have_children = GETPOSTINT('can_have_children');
|
|
$buildingType->has_product = GETPOSTINT('has_product');
|
|
$buildingType->position = GETPOSTINT('position');
|
|
$buildingType->active = GETPOSTINT('active');
|
|
|
|
$result = $buildingType->update($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordModifiedSuccessfully'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF']);
|
|
exit;
|
|
} else {
|
|
setEventMessages($buildingType->error, $buildingType->errors, 'errors');
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($action == 'confirm_delete' && $confirm == 'yes' && $user->admin) {
|
|
$result = $buildingType->fetch($id);
|
|
if ($result > 0) {
|
|
$result = $buildingType->delete($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
|
} else {
|
|
setEventMessages($langs->trans($buildingType->error), $buildingType->errors, 'errors');
|
|
}
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF']);
|
|
exit;
|
|
}
|
|
|
|
// Load data for edit
|
|
if (($action == 'edit' || $action == 'delete') && $id > 0) {
|
|
$result = $buildingType->fetch($id);
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$page_name = "BuildingTypesSetup";
|
|
llxHeader('', $langs->trans($page_name), '', '', 0, 0, '', '', '', 'mod-kundenkarte page-admin-building_types');
|
|
|
|
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
|
|
print load_fiche_titre($langs->trans($page_name), $linkback, 'object_kundenkarte@kundenkarte');
|
|
|
|
print '<div class="fichecenter">';
|
|
|
|
$head = kundenkarteAdminPrepareHead();
|
|
print dol_get_fiche_head($head, 'building_types', $langs->trans("Module500015Name"), -1, 'kundenkarte@kundenkarte');
|
|
|
|
// Delete confirmation
|
|
if ($action == 'delete') {
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?id='.$buildingType->id,
|
|
$langs->trans('DeleteBuildingType'),
|
|
$langs->trans('ConfirmDeleteBuildingType', $buildingType->label),
|
|
'confirm_delete',
|
|
'',
|
|
0,
|
|
1
|
|
);
|
|
}
|
|
|
|
// Level type filter
|
|
$levelTypes = BuildingType::getLevelTypes();
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<form method="get" action="'.$_SERVER['PHP_SELF'].'">';
|
|
print '<div class="inline-block valignmiddle" style="margin-bottom: 10px;">';
|
|
print '<label for="level_filter">'.$langs->trans('FilterByLevel').': </label>';
|
|
print '<select name="level_filter" id="level_filter" class="flat minwidth200" onchange="this.form.submit()">';
|
|
print '<option value="">'.$langs->trans('All').'</option>';
|
|
foreach ($levelTypes as $code => $label) {
|
|
$selected = ($levelFilter == $code) ? ' selected' : '';
|
|
print '<option value="'.$code.'"'.$selected.'>'.$label.'</option>';
|
|
}
|
|
print '</select>';
|
|
print '</div>';
|
|
print '</form>';
|
|
print '</div>';
|
|
|
|
// Add/Edit form
|
|
if ($action == 'create' || $action == 'edit') {
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="'.($action == 'edit' ? 'update' : 'add').'">';
|
|
if ($action == 'edit') {
|
|
print '<input type="hidden" name="id" value="'.$buildingType->id.'">';
|
|
}
|
|
|
|
print '<table class="border centpercent tableforfield">';
|
|
|
|
// Ref
|
|
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Ref').'</td><td>';
|
|
if ($action == 'edit' && $buildingType->is_system) {
|
|
print '<input type="hidden" name="ref" value="'.$buildingType->ref.'">';
|
|
print $buildingType->ref.' <span class="opacitymedium">('.$langs->trans('SystemType').')</span>';
|
|
} else {
|
|
print '<input type="text" name="ref" class="flat minwidth200" value="'.($buildingType->ref ?: '').'" maxlength="50">';
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Label
|
|
print '<tr><td class="fieldrequired">'.$langs->trans('Label').'</td><td>';
|
|
print '<input type="text" name="label" class="flat minwidth300" value="'.dol_escape_htmltag($buildingType->label ?: '').'">';
|
|
print '</td></tr>';
|
|
|
|
// Label Short
|
|
print '<tr><td>'.$langs->trans('LabelShort').'</td><td>';
|
|
print '<input type="text" name="label_short" class="flat minwidth150" value="'.dol_escape_htmltag($buildingType->label_short ?: '').'" maxlength="32">';
|
|
print '</td></tr>';
|
|
|
|
// Level Type
|
|
print '<tr><td>'.$langs->trans('LevelType').'</td><td>';
|
|
print '<select name="level_type" class="flat minwidth200">';
|
|
print '<option value="">--</option>';
|
|
foreach ($levelTypes as $code => $label) {
|
|
$selected = ($buildingType->level_type == $code) ? ' selected' : '';
|
|
print '<option value="'.$code.'"'.$selected.'>'.$label.'</option>';
|
|
}
|
|
print '</select>';
|
|
print '</td></tr>';
|
|
|
|
// Icon
|
|
print '<tr><td>'.$langs->trans('Icon').'</td><td>';
|
|
print '<input type="text" name="icon" class="flat minwidth200" value="'.dol_escape_htmltag($buildingType->icon ?: '').'" placeholder="fa-home">';
|
|
if ($buildingType->icon) {
|
|
print ' <i class="fas '.$buildingType->icon.'"></i>';
|
|
}
|
|
print ' <span class="opacitymedium">(FontAwesome, z.B. fa-home, fa-building)</span>';
|
|
print '</td></tr>';
|
|
|
|
// Color
|
|
print '<tr><td>'.$langs->trans('Color').'</td><td>';
|
|
print '<input type="color" name="color" id="color_picker" value="'.($buildingType->color ?: '#3498db').'" style="width:50px;height:30px;vertical-align:middle;">';
|
|
print ' <input type="text" name="color_text" id="color_text" class="flat" value="'.($buildingType->color ?: '#3498db').'" size="10" onchange="document.getElementById(\'color_picker\').value=this.value;">';
|
|
print '</td></tr>';
|
|
|
|
// Can have children
|
|
print '<tr><td>'.$langs->trans('CanHaveChildren').'</td><td>';
|
|
print '<input type="checkbox" name="can_have_children" value="1"'.($buildingType->can_have_children || $action != 'edit' ? ' checked' : '').'>';
|
|
print '</td></tr>';
|
|
|
|
// Produkt-Zuordnung erlauben
|
|
print '<tr><td>'.$langs->trans('HasProduct').'</td><td>';
|
|
print '<input type="checkbox" name="has_product" value="1"'.($buildingType->has_product ? ' checked' : '').'>';
|
|
print ' <span class="opacitymedium">('.$langs->trans('HasProductHelp').')</span>';
|
|
print '</td></tr>';
|
|
|
|
// Position
|
|
print '<tr><td>'.$langs->trans('Position').'</td><td>';
|
|
$defaultPos = $action == 'create' ? $buildingType->getNextPosition() : $buildingType->position;
|
|
print '<input type="number" name="position" class="flat" value="'.(int)$defaultPos.'" min="0" step="10">';
|
|
print '</td></tr>';
|
|
|
|
// Active
|
|
print '<tr><td>'.$langs->trans('Active').'</td><td>';
|
|
print '<input type="checkbox" name="active" value="1"'.($buildingType->active || $action != 'edit' ? ' checked' : '').'>';
|
|
print '</td></tr>';
|
|
|
|
// Description
|
|
print '<tr><td>'.$langs->trans('Description').'</td><td>';
|
|
print '<textarea name="description" class="flat" rows="3" cols="60">'.$buildingType->description.'</textarea>';
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
|
|
print '<div class="center" style="margin-top: 10px;">';
|
|
print '<input type="submit" class="button button-save" value="'.$langs->trans('Save').'">';
|
|
print ' <a class="button button-cancel" href="'.$_SERVER['PHP_SELF'].'">'.$langs->trans('Cancel').'</a>';
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
|
|
// Sync color inputs
|
|
print '<script>
|
|
document.getElementById("color_picker").addEventListener("input", function() {
|
|
document.getElementById("color_text").value = this.value;
|
|
});
|
|
</script>';
|
|
|
|
} else {
|
|
// List of building types
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<table class="noborder centpercent">';
|
|
|
|
// Header
|
|
print '<tr class="liste_titre">';
|
|
print '<td>'.$langs->trans('Ref').'</td>';
|
|
print '<td>'.$langs->trans('Label').'</td>';
|
|
print '<td>'.$langs->trans('LevelType').'</td>';
|
|
print '<td class="center">'.$langs->trans('Icon').'</td>';
|
|
print '<td class="center">'.$langs->trans('Color').'</td>';
|
|
print '<td class="center">'.$langs->trans('Position').'</td>';
|
|
print '<td class="center">'.$langs->trans('Active').'</td>';
|
|
print '<td class="center">'.$langs->trans('Actions').'</td>';
|
|
print '</tr>';
|
|
|
|
// Fetch types
|
|
$types = $buildingType->fetchAll(0, $levelFilter);
|
|
|
|
if (count($types) > 0) {
|
|
foreach ($types as $type) {
|
|
print '<tr class="oddeven">';
|
|
|
|
// Ref
|
|
print '<td>'.$type->ref;
|
|
if ($type->is_system) {
|
|
print ' <span class="badge badge-secondary">'.$langs->trans('System').'</span>';
|
|
}
|
|
print '</td>';
|
|
|
|
// Label
|
|
print '<td>';
|
|
if ($type->icon) {
|
|
print '<i class="fas '.$type->icon.'" style="color:'.$type->color.';margin-right:5px;"></i> ';
|
|
}
|
|
print dol_escape_htmltag($type->label);
|
|
if ($type->label_short) {
|
|
print ' <span class="opacitymedium">('.$type->label_short.')</span>';
|
|
}
|
|
print '</td>';
|
|
|
|
// Level Type
|
|
print '<td>'.$type->getLevelTypeLabel().'</td>';
|
|
|
|
// Icon
|
|
print '<td class="center">';
|
|
if ($type->icon) {
|
|
print '<i class="fas '.$type->icon.'"></i> '.$type->icon;
|
|
}
|
|
print '</td>';
|
|
|
|
// Color
|
|
print '<td class="center">';
|
|
if ($type->color) {
|
|
print '<span style="display:inline-block;width:20px;height:20px;background:'.$type->color.';border:1px solid #ccc;border-radius:3px;vertical-align:middle;"></span> '.$type->color;
|
|
}
|
|
print '</td>';
|
|
|
|
// Position
|
|
print '<td class="center">'.$type->position.'</td>';
|
|
|
|
// Active
|
|
print '<td class="center">';
|
|
print $type->active ? '<span class="badge badge-status4">'.$langs->trans('Yes').'</span>' : '<span class="badge badge-status5">'.$langs->trans('No').'</span>';
|
|
print '</td>';
|
|
|
|
// Actions
|
|
print '<td class="center nowrap">';
|
|
print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=edit&id='.$type->id.'">'.img_edit().'</a>';
|
|
if (!$type->is_system) {
|
|
print ' <a class="deletefielda" href="'.$_SERVER['PHP_SELF'].'?action=delete&id='.$type->id.'">'.img_delete().'</a>';
|
|
}
|
|
print '</td>';
|
|
|
|
print '</tr>';
|
|
}
|
|
} else {
|
|
print '<tr class="oddeven"><td colspan="8" class="opacitymedium">'.$langs->trans('NoRecordFound').'</td></tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
// Add button
|
|
print '<div class="tabsAction">';
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=create">'.$langs->trans('AddBuildingType').'</a>';
|
|
print '</div>';
|
|
}
|
|
|
|
print dol_get_fiche_end();
|
|
print '</div>';
|
|
|
|
llxFooter();
|
|
$db->close();
|