- 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>
982 lines
36 KiB
PHP
Executable file
982 lines
36 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* Mein Betrieb: Baumansicht für eigene Maschinen, Werkzeuge und Geräte
|
|
* Multi-System mit System-Tabs (wie Kunden-Anlagen)
|
|
*/
|
|
|
|
// 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/class/html.form.class.php';
|
|
dol_include_once('/kundenkarte/class/anlage.class.php');
|
|
dol_include_once('/kundenkarte/class/anlagetype.class.php');
|
|
dol_include_once('/kundenkarte/class/anlagefile.class.php');
|
|
dol_include_once('/kundenkarte/class/anlageaccessory.class.php');
|
|
dol_include_once('/kundenkarte/lib/kundenkarte.lib.php');
|
|
|
|
// Übersetzungen
|
|
$langs->loadLangs(array('companies', 'kundenkarte@kundenkarte'));
|
|
|
|
// Berechtigungen
|
|
if (!$user->hasRight('kundenkarte', 'read')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
$permissiontoread = $user->hasRight('kundenkarte', 'read');
|
|
$permissiontoadd = $user->hasRight('kundenkarte', 'write');
|
|
$permissiontodelete = $user->hasRight('kundenkarte', 'delete');
|
|
|
|
$action = GETPOST('action', 'aZ09');
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$systemId = GETPOSTINT('system');
|
|
$anlageId = GETPOSTINT('anlage_id');
|
|
$parentId = GETPOSTINT('parent_id');
|
|
|
|
// Virtuelle Firma-ID für "Mein Betrieb" - braucht keinen echten Societe-Eintrag
|
|
// Die Anlage-Tabelle verwendet diese ID nur als Gruppierung
|
|
$socId = 99999999;
|
|
|
|
// ALLE verfügbaren Systeme laden
|
|
$allSystems = array();
|
|
$sql = "SELECT rowid, code, label, picto, color FROM ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system WHERE active = 1 ORDER BY position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
$allSystems[$obj->rowid] = $obj;
|
|
}
|
|
}
|
|
|
|
// Für diesen virtuellen Betrieb aktivierte Systeme laden
|
|
$customerSystems = array();
|
|
$sql = "SELECT ss.rowid, ss.fk_system, s.code, s.label, s.picto, s.color";
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."kundenkarte_societe_system ss";
|
|
$sql .= " JOIN ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system s ON s.rowid = ss.fk_system";
|
|
$sql .= " WHERE ss.fk_soc = ".((int) $socId)." AND (ss.fk_contact IS NULL OR ss.fk_contact = 0) AND ss.active = 1 AND s.active = 1";
|
|
$sql .= " AND s.code != 'GLOBAL'";
|
|
$sql .= " ORDER BY s.position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
$customerSystems[$obj->fk_system] = $obj;
|
|
}
|
|
}
|
|
|
|
// Standard: Erstes aktiviertes System falls nicht angegeben
|
|
if (empty($systemId) && !empty($customerSystems)) {
|
|
$systemId = array_key_first($customerSystems);
|
|
}
|
|
|
|
// Objekte initialisieren
|
|
$form = new Form($db);
|
|
$anlage = new Anlage($db);
|
|
$anlageType = new AnlageType($db);
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
// System hinzufügen
|
|
if ($action == 'add_system' && $permissiontoadd) {
|
|
$newSystemId = GETPOSTINT('new_system_id');
|
|
if ($newSystemId > 0 && !isset($customerSystems[$newSystemId])) {
|
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."kundenkarte_societe_system";
|
|
$sql .= " (entity, fk_soc, fk_contact, fk_system, date_creation, fk_user_creat, active)";
|
|
$sql .= " VALUES (".$conf->entity.", ".((int) $socId).", 0, ".((int) $newSystemId).", NOW(), ".((int) $user->id).", 1)";
|
|
$result = $db->query($sql);
|
|
if ($result) {
|
|
setEventMessages($langs->trans('SystemAdded'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?system='.$newSystemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($db->lasterror(), null, 'errors');
|
|
}
|
|
}
|
|
$action = '';
|
|
}
|
|
|
|
// System entfernen
|
|
if ($action == 'confirm_remove_system' && $confirm == 'yes' && $permissiontodelete) {
|
|
$removeSystemId = GETPOSTINT('remove_system_id');
|
|
if ($removeSystemId > 0) {
|
|
// Prüfen ob System noch Elemente hat
|
|
$sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."kundenkarte_anlage WHERE fk_soc = ".((int) $socId)." AND (fk_contact IS NULL OR fk_contact = 0) AND fk_system = ".((int) $removeSystemId);
|
|
$resql = $db->query($sql);
|
|
$obj = $db->fetch_object($resql);
|
|
|
|
if ($obj->cnt > 0) {
|
|
setEventMessages($langs->trans('ErrorSystemHasElements'), null, 'errors');
|
|
} else {
|
|
$sql = "DELETE FROM ".MAIN_DB_PREFIX."kundenkarte_societe_system WHERE fk_soc = ".((int) $socId)." AND (fk_contact IS NULL OR fk_contact = 0) AND fk_system = ".((int) $removeSystemId);
|
|
$db->query($sql);
|
|
setEventMessages($langs->trans('SystemRemoved'), null, 'mesgs');
|
|
|
|
unset($customerSystems[$removeSystemId]);
|
|
if (!empty($customerSystems)) {
|
|
$systemId = array_key_first($customerSystems);
|
|
} else {
|
|
$systemId = 0;
|
|
}
|
|
}
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF'].($systemId ? '?system='.$systemId : ''));
|
|
exit;
|
|
}
|
|
|
|
if ($action == 'add' && $permissiontoadd) {
|
|
$anlage->label = GETPOST('label', 'alphanohtml');
|
|
$anlage->fk_soc = $socId;
|
|
$anlage->fk_anlage_type = GETPOSTINT('fk_anlage_type');
|
|
$anlage->fk_parent = GETPOSTINT('fk_parent');
|
|
$anlage->fk_system = $systemId;
|
|
$anlage->fk_product = GETPOSTINT('fk_product') > 0 ? GETPOSTINT('fk_product') : null;
|
|
$anlage->note_private = isset($_POST['note_private']) ? $_POST['note_private'] : '';
|
|
$anlage->status = 1;
|
|
|
|
// Dynamische Felder
|
|
$type = new AnlageType($db);
|
|
if ($type->fetch($anlage->fk_anlage_type) > 0) {
|
|
$fieldValues = array();
|
|
$fields = $type->fetchFields();
|
|
foreach ($fields as $field) {
|
|
if ($field->field_type === 'header') continue;
|
|
$value = GETPOST('field_'.$field->field_code, 'alphanohtml');
|
|
if ($value !== '') {
|
|
$fieldValues[$field->field_code] = $value;
|
|
}
|
|
}
|
|
$anlage->setFieldValues($fieldValues);
|
|
}
|
|
|
|
$result = $anlage->create($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?system='.$systemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
$action = 'create';
|
|
}
|
|
}
|
|
|
|
if ($action == 'update' && $permissiontoadd) {
|
|
$anlage->fetch($anlageId);
|
|
$anlage->label = GETPOST('label', 'alphanohtml');
|
|
$anlage->fk_anlage_type = GETPOSTINT('fk_anlage_type');
|
|
$anlage->fk_parent = GETPOSTINT('fk_parent');
|
|
$anlage->fk_product = GETPOSTINT('fk_product') > 0 ? GETPOSTINT('fk_product') : null;
|
|
$anlage->note_private = isset($_POST['note_private']) ? $_POST['note_private'] : '';
|
|
|
|
// Dynamische Felder
|
|
$type = new AnlageType($db);
|
|
if ($type->fetch($anlage->fk_anlage_type) > 0) {
|
|
$fieldValues = array();
|
|
$fields = $type->fetchFields();
|
|
foreach ($fields as $field) {
|
|
if ($field->field_type === 'header') continue;
|
|
$value = GETPOST('field_'.$field->field_code, 'alphanohtml');
|
|
if ($value !== '') {
|
|
$fieldValues[$field->field_code] = $value;
|
|
}
|
|
}
|
|
$anlage->setFieldValues($fieldValues);
|
|
}
|
|
|
|
$result = $anlage->update($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?system='.$systemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
$action = 'edit';
|
|
}
|
|
}
|
|
|
|
if ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
|
|
$anlage->fetch($anlageId);
|
|
$result = $anlage->delete($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF']);
|
|
exit;
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$title = $langs->trans('CompanyTools');
|
|
$jsFiles = array('/kundenkarte/js/kundenkarte.js?v='.time());
|
|
$cssFiles = array('/kundenkarte/css/kundenkarte.css?v='.time());
|
|
|
|
llxHeader('', $title, '', '', 0, 0, $jsFiles, $cssFiles);
|
|
|
|
print load_fiche_titre($title, '', 'fa-wrench');
|
|
|
|
print '<div class="fichecenter">';
|
|
|
|
// Bestätigungsdialoge
|
|
if ($action == 'delete') {
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?system='.$systemId.'&anlage_id='.$anlageId,
|
|
$langs->trans('DeleteElement'),
|
|
$langs->trans('ConfirmDeleteElement'),
|
|
'confirm_delete',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
if ($action == 'remove_system') {
|
|
$removeSystemId = GETPOSTINT('remove_system_id');
|
|
$sysLabel = isset($customerSystems[$removeSystemId]) ? $customerSystems[$removeSystemId]->label : '';
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?remove_system_id='.$removeSystemId,
|
|
$langs->trans('RemoveSystem'),
|
|
$langs->trans('ConfirmRemoveSystem', $sysLabel),
|
|
'confirm_remove_system',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
// System-Tabs
|
|
print '<div class="kundenkarte-system-tabs-wrapper">';
|
|
print '<div class="kundenkarte-system-tabs">';
|
|
foreach ($customerSystems as $sysId => $sys) {
|
|
$activeClass = ($sysId == $systemId) ? ' active' : '';
|
|
print '<div class="kundenkarte-system-tab'.$activeClass.'" data-system="'.$sysId.'">';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?system='.$sysId.'" style="text-decoration:none;color:inherit;display:flex;align-items:center;gap:8px;">';
|
|
if ($sys->picto) {
|
|
print '<span class="kundenkarte-system-tab-icon" style="color:'.$sys->color.';">'.kundenkarte_render_icon($sys->picto).'</span>';
|
|
}
|
|
print '<span>'.dol_escape_htmltag($sys->label).'</span>';
|
|
print '</a>';
|
|
// Entfernen-Button (nur beim aktiven Tab)
|
|
if ($permissiontodelete && $sysId == $systemId) {
|
|
print ' <a href="'.$_SERVER['PHP_SELF'].'?action=remove_system&remove_system_id='.$sysId.'" class="kundenkarte-system-remove" title="'.$langs->trans('RemoveSystem').'"><i class="fa fa-times"></i></a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
|
|
// System hinzufügen Button
|
|
if ($permissiontoadd) {
|
|
$availableSystems = array_diff_key($allSystems, $customerSystems);
|
|
// GLOBAL ausschließen
|
|
foreach ($availableSystems as $k => $v) {
|
|
if ($v->code === 'GLOBAL') unset($availableSystems[$k]);
|
|
}
|
|
if (!empty($availableSystems)) {
|
|
print '<button type="button" class="button small kundenkarte-add-system-btn" onclick="document.getElementById(\'add-system-form\').style.display=\'block\';">';
|
|
print '<i class="fa fa-plus"></i> '.$langs->trans('AddSystem');
|
|
print '</button>';
|
|
}
|
|
}
|
|
print '</div>';
|
|
|
|
// Steuerungs-Buttons (nur in Baumansicht)
|
|
$isTreeView = !in_array($action, array('create', 'edit', 'view'));
|
|
if ($isTreeView && $systemId > 0) {
|
|
print '<div class="kundenkarte-tree-controls">';
|
|
print '<button type="button" class="kundenkarte-view-toggle" id="btn-compact-mode" title="Kompakte Ansicht">';
|
|
print '<i class="fa fa-compress"></i> <span>Kompakt</span>';
|
|
print '</button>';
|
|
print '<button type="button" class="button small" id="btn-expand-all" title="'.$langs->trans('ExpandAll').'">';
|
|
print '<i class="fa fa-expand"></i> '.$langs->trans('ExpandAll');
|
|
print '</button>';
|
|
print '<button type="button" class="button small" id="btn-collapse-all" title="'.$langs->trans('CollapseAll').'">';
|
|
print '<i class="fa fa-compress"></i> '.$langs->trans('CollapseAll');
|
|
print '</button>';
|
|
$showDecomm = getDolGlobalInt('KUNDENKARTE_SHOW_DECOMMISSIONED', 0);
|
|
print '<button type="button" class="button small'.($showDecomm ? ' active' : '').'" id="btn-toggle-decommissioned" title="'.$langs->trans('ShowDecommissioned').'">';
|
|
print '<i class="fa '.($showDecomm ? 'fa-eye' : 'fa-eye-slash').'"></i> <span>'.$langs->trans('Decommissioned').'</span>';
|
|
print '</button>';
|
|
print '</div>';
|
|
}
|
|
|
|
print '</div>'; // End system-tabs-wrapper
|
|
|
|
// System-Hinzufügen-Formular (versteckt)
|
|
if ($permissiontoadd && !empty($availableSystems)) {
|
|
print '<div id="add-system-form" class="kundenkarte-add-system-form" style="display:none;margin-bottom:15px;">';
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="add_system">';
|
|
print '<strong>'.$langs->trans('SelectSystemToAdd').':</strong> ';
|
|
print '<select name="new_system_id" class="flat">';
|
|
print '<option value="">'.$langs->trans('Select').'</option>';
|
|
foreach ($availableSystems as $avSys) {
|
|
print '<option value="'.$avSys->rowid.'">'.dol_escape_htmltag($avSys->label).'</option>';
|
|
}
|
|
print '</select>';
|
|
print ' <button type="submit" class="button small">'.$langs->trans('Add').'</button>';
|
|
print ' <button type="button" class="button small" onclick="document.getElementById(\'add-system-form\').style.display=\'none\';">'.$langs->trans('Cancel').'</button>';
|
|
print '</form>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Prüfen ob Systeme konfiguriert sind
|
|
if (empty($customerSystems)) {
|
|
print '<div class="opacitymedium" style="padding:20px;text-align:center;">';
|
|
print '<i class="fa fa-info-circle" style="font-size:24px;margin-bottom:10px;"></i><br>';
|
|
print $langs->trans('NoSystemsConfigured').'<br><br>';
|
|
if ($permissiontoadd && !empty($allSystems)) {
|
|
print $langs->trans('ClickAddSystemToStart');
|
|
} else {
|
|
print $langs->trans('ContactAdminToAddSystems');
|
|
}
|
|
print '</div>';
|
|
} elseif ($systemId > 0) {
|
|
|
|
// Typen für ausgewähltes System laden
|
|
$types = $anlageType->fetchAllBySystem($systemId, 1, 1);
|
|
|
|
if (in_array($action, array('create', 'edit', 'view'))) {
|
|
// Formular oder Detail-Ansicht
|
|
|
|
if ($action != 'create' && $anlageId > 0) {
|
|
$anlage->fetch($anlageId);
|
|
$type = new AnlageType($db);
|
|
$type->fetch($anlage->fk_anlage_type);
|
|
$type->fetchFields();
|
|
}
|
|
|
|
print '<div class="kundenkarte-element-form">';
|
|
|
|
if ($action == 'view') {
|
|
// Detail-Ansicht
|
|
print '<h3>'.dol_escape_htmltag($anlage->label).'</h3>';
|
|
|
|
print '<table class="border centpercent">';
|
|
|
|
print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>';
|
|
|
|
// Zugeordnetes Produkt (nur wenn Typ es erlaubt)
|
|
if ($type->has_product && $anlage->fk_product > 0) {
|
|
$product = new Product($db);
|
|
if ($product->fetch($anlage->fk_product) > 0) {
|
|
print '<tr><td>'.$langs->trans('Product').'</td>';
|
|
print '<td><a href="'.DOL_URL_ROOT.'/product/card.php?id='.$product->id.'">'.dol_escape_htmltag($product->ref).'</a>';
|
|
print ' - '.dol_escape_htmltag($product->label);
|
|
if ($product->price > 0) {
|
|
print ' <span class="opacitymedium">('.price($product->price).' €)</span>';
|
|
}
|
|
print '</td></tr>';
|
|
}
|
|
}
|
|
|
|
// Dynamische Felder
|
|
$fieldValues = $anlage->getFieldValues();
|
|
$typeFieldsList = $type->fetchFields();
|
|
foreach ($typeFieldsList as $field) {
|
|
if ($field->field_type === 'header') {
|
|
print '<tr class="liste_titre"><th colspan="2" style="padding:8px;">'.dol_escape_htmltag($field->field_label).'</th></tr>';
|
|
} else {
|
|
$value = isset($fieldValues[$field->field_code]) ? $fieldValues[$field->field_code] : '';
|
|
if ($value !== '') {
|
|
print '<tr><td>'.dol_escape_htmltag($field->field_label).'</td>';
|
|
if ($field->field_type === 'date' && $value) {
|
|
print '<td>'.dol_print_date(strtotime($value), 'day').'</td></tr>';
|
|
} elseif ($field->field_type === 'checkbox') {
|
|
print '<td>'.($value ? $langs->trans('Yes') : $langs->trans('No')).'</td></tr>';
|
|
} else {
|
|
print '<td>'.dol_escape_htmltag($value).'</td></tr>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($anlage->note_private) {
|
|
print '<tr><td>'.$langs->trans('FieldNotes').'</td>';
|
|
print '<td>'.dol_htmlentitiesbr($anlage->note_private).'</td></tr>';
|
|
}
|
|
|
|
// Ausgebaut-Status
|
|
if (!empty($anlage->decommissioned)) {
|
|
print '<tr><td>'.$langs->trans('Decommissioned').'</td>';
|
|
print '<td><span class="badge-decommissioned"><i class="fa fa-power-off"></i> '.$langs->trans('Decommissioned').'</span>';
|
|
if (!empty($anlage->date_decommissioned)) {
|
|
print ' '.dol_print_date(strtotime($anlage->date_decommissioned), 'day');
|
|
}
|
|
print '</td></tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
|
|
// Zubehör-Bereich (nur wenn Typ has_accessories hat)
|
|
if ($type->has_accessories) {
|
|
$accessoryObj = new AnlageAccessory($db);
|
|
$accessories = $accessoryObj->fetchAllByAnlage($anlageId);
|
|
|
|
print '<br><h4><i class="fa fa-puzzle-piece"></i> '.$langs->trans('Accessories').'</h4>';
|
|
|
|
if (!empty($accessories)) {
|
|
print '<div class="div-table-responsive">';
|
|
print '<table class="tagtable liste">';
|
|
print '<tr class="liste_titre">';
|
|
print '<th>'.$langs->trans('ProductRef').'</th>';
|
|
print '<th>'.$langs->trans('Label').'</th>';
|
|
print '<th class="right">'.$langs->trans('Qty').'</th>';
|
|
print '<th>'.$langs->trans('Note').'</th>';
|
|
if ($permissiontodelete) {
|
|
print '<th class="right">'.$langs->trans('Action').'</th>';
|
|
}
|
|
print '</tr>';
|
|
foreach ($accessories as $acc) {
|
|
print '<tr>';
|
|
print '<td><a href="'.DOL_URL_ROOT.'/product/card.php?id='.$acc->fk_product.'">'.dol_escape_htmltag($acc->product_ref).'</a></td>';
|
|
print '<td>'.dol_escape_htmltag($acc->product_label).'</td>';
|
|
print '<td class="right">'.$acc->qty.'</td>';
|
|
print '<td>'.dol_escape_htmltag($acc->note).'</td>';
|
|
if ($permissiontodelete) {
|
|
print '<td class="right"><a href="#" class="btn-delete-accessory" data-id="'.$acc->id.'" title="'.$langs->trans('Delete').'"><i class="fa fa-trash"></i></a></td>';
|
|
}
|
|
print '</tr>';
|
|
}
|
|
print '</table>';
|
|
print '</div>';
|
|
} else {
|
|
print '<p class="opacitymedium">'.$langs->trans('NoAccessories').'</p>';
|
|
}
|
|
|
|
// Zubehör hinzufügen
|
|
if ($permissiontoadd) {
|
|
print '<div id="add-accessory-form" style="margin-top:10px;">';
|
|
print '<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;">';
|
|
print '<input type="text" id="accessory_product_search" class="flat minwidth300" placeholder="'.$langs->trans('SearchProduct').'...">';
|
|
print '<input type="hidden" id="accessory_product_id" value="">';
|
|
print '<input type="number" id="accessory_qty" class="flat" value="1" min="1" style="width:80px;">';
|
|
print '<button type="button" id="btn-add-accessory" class="button small" disabled>'.$langs->trans('Add').'</button>';
|
|
print '</div>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Bestellfunktion
|
|
if ($permissiontoadd && !empty($accessories)) {
|
|
print '<div style="margin-top:15px;padding:10px;border:1px solid #444;border-radius:4px;">';
|
|
print '<h5 style="margin:0 0 10px 0;"><i class="fa fa-shopping-cart"></i> '.$langs->trans('OrderAccessories').'</h5>';
|
|
print '<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;">';
|
|
print '<select id="supplier_select" class="flat minwidth200">';
|
|
print '<option value="">'.$langs->trans('SelectSupplier').'</option>';
|
|
// Lieferanten laden
|
|
$sqlSupp = "SELECT s.rowid, s.nom FROM ".MAIN_DB_PREFIX."societe s WHERE s.fournisseur = 1 AND s.status = 1 ORDER BY s.nom";
|
|
$resSupp = $db->query($sqlSupp);
|
|
if ($resSupp) {
|
|
while ($objSupp = $db->fetch_object($resSupp)) {
|
|
print '<option value="'.$objSupp->rowid.'">'.dol_escape_htmltag($objSupp->nom).'</option>';
|
|
}
|
|
}
|
|
print '</select>';
|
|
print '<button type="button" id="btn-order-accessories" class="button small">'.$langs->trans('CreateSupplierOrder').'</button>';
|
|
print '</div>';
|
|
print '</div>';
|
|
}
|
|
}
|
|
|
|
// Aktions-Buttons
|
|
print '<div class="tabsAction">';
|
|
if ($permissiontoadd) {
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=edit&anlage_id='.$anlageId.'">'.$langs->trans('Modify').'</a>';
|
|
}
|
|
if ($permissiontodelete) {
|
|
print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=delete&anlage_id='.$anlageId.'">'.$langs->trans('Delete').'</a>';
|
|
}
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'">'.$langs->trans('Back').'</a>';
|
|
print '</div>';
|
|
|
|
} else {
|
|
// Erstellen/Bearbeiten-Formular
|
|
$isEdit = ($action == 'edit');
|
|
$formAction = $isEdit ? 'update' : 'add';
|
|
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="'.$formAction.'">';
|
|
print '<input type="hidden" name="system" value="'.$systemId.'">';
|
|
if ($isEdit) {
|
|
print '<input type="hidden" name="anlage_id" value="'.$anlageId.'">';
|
|
}
|
|
|
|
print '<table class="border centpercent" id="element_form_table">';
|
|
|
|
// Label
|
|
$labelValue = $isEdit ? $anlage->label : GETPOST('label');
|
|
print '<tr><td class="titlefield fieldrequired">'.$langs->trans('Label').'</td>';
|
|
print '<td><input type="text" name="label" class="flat minwidth300" value="'.dol_escape_htmltag($labelValue).'" required></td></tr>';
|
|
|
|
// Typ
|
|
print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td>';
|
|
print '<td><select name="fk_anlage_type" class="flat minwidth200" id="select_type" required>';
|
|
print '<option value="">'.$langs->trans('SelectType').'</option>';
|
|
foreach ($types as $t) {
|
|
$selected = ($isEdit && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
|
|
print '<option value="'.$t->id.'" data-has-product="'.($t->has_product ? '1' : '0').'" data-has-accessories="'.($t->has_accessories ? '1' : '0').'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>';
|
|
}
|
|
print '</select>';
|
|
if (empty($types)) {
|
|
print '<br><span class="warning">'.$langs->trans('NoTypesDefinedForSystem').' <a href="'.dol_buildpath('/kundenkarte/admin/anlage_types.php', 1).'">'.$langs->trans('GoToTypeAdmin').'</a></span>';
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Übergeordnetes Element
|
|
$tree = $anlage->fetchTree($socId, $systemId);
|
|
$selectedParent = $isEdit ? $anlage->fk_parent : $parentId;
|
|
$excludeId = $isEdit ? $anlageId : 0;
|
|
print '<tr><td>'.$langs->trans('SelectParent').'</td>';
|
|
print '<td><select name="fk_parent" class="flat minwidth200">';
|
|
print '<option value="0">('.$langs->trans('Root').')</option>';
|
|
werkzeuge_printTreeOptions($tree, $selectedParent, $excludeId);
|
|
print '</select></td></tr>';
|
|
|
|
// Produkt-Zuordnung (wird per JS ein-/ausgeblendet je nach Typ)
|
|
$productValue = '';
|
|
$productId = 0;
|
|
if ($isEdit && $anlage->fk_product > 0) {
|
|
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
|
$product = new Product($db);
|
|
if ($product->fetch($anlage->fk_product) > 0) {
|
|
$productValue = $product->ref.' - '.$product->label;
|
|
$productId = $product->id;
|
|
}
|
|
}
|
|
print '<tr id="row_product" style="display:none;"><td>'.$langs->trans('Product').'</td>';
|
|
print '<td>';
|
|
print '<input type="text" id="product_search" class="flat minwidth300" placeholder="'.$langs->trans('SearchProduct').'..." value="'.dol_escape_htmltag($productValue).'">';
|
|
print '<input type="hidden" name="fk_product" id="fk_product" value="'.$productId.'">';
|
|
print '</td></tr>';
|
|
|
|
// Dynamische Felder werden per JS geladen
|
|
print '<tbody id="dynamic_fields"></tbody>';
|
|
|
|
// Notizen
|
|
print '<tr><td>'.$langs->trans('FieldNotes').'</td>';
|
|
$noteValue = $isEdit ? $anlage->note_private : (isset($_POST['note_private']) ? $_POST['note_private'] : '');
|
|
print '<td><textarea name="note_private" class="flat minwidth300" rows="3">'.htmlspecialchars($noteValue, ENT_QUOTES, 'UTF-8').'</textarea></td></tr>';
|
|
|
|
print '</table>';
|
|
|
|
print '<div class="center" style="margin-top:20px;">';
|
|
print '<button type="submit" class="button button-save">'.$langs->trans('Save').'</button>';
|
|
print ' <a class="button button-cancel" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'">'.$langs->trans('Cancel').'</a>';
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
}
|
|
|
|
print '</div>';
|
|
|
|
} else {
|
|
// Baumansicht
|
|
|
|
if ($permissiontoadd) {
|
|
print '<div style="margin-bottom:15px;">';
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=create">';
|
|
print '<i class="fa fa-plus"></i> '.$langs->trans('AddElement');
|
|
print '</a>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Baum laden
|
|
$tree = $anlage->fetchTree($socId, $systemId);
|
|
|
|
// Feld-Metadaten laden
|
|
$typeFieldsMap = array();
|
|
$sql = "SELECT f.*, f.fk_anlage_type FROM ".MAIN_DB_PREFIX."kundenkarte_anlage_type_field f WHERE f.active = 1 ORDER BY f.position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
if (!isset($typeFieldsMap[$obj->fk_anlage_type])) {
|
|
$typeFieldsMap[$obj->fk_anlage_type] = array();
|
|
}
|
|
$typeFieldsMap[$obj->fk_anlage_type][] = $obj;
|
|
}
|
|
$db->free($resql);
|
|
}
|
|
|
|
if (!empty($tree)) {
|
|
print '<div class="kundenkarte-tree'.($showDecomm ? ' show-decommissioned' : '').'" data-system="'.$systemId.'" data-socid="'.$socId.'">';
|
|
werkzeuge_printTree($tree, $socId, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap);
|
|
print '</div>';
|
|
} else {
|
|
print '<div class="opacitymedium" style="padding:20px;text-align:center;">';
|
|
print '<i class="fa fa-wrench" style="font-size:48px;margin-bottom:15px;color:#666;"></i><br>';
|
|
print $langs->trans('NoToolsYet').'<br><br>';
|
|
if ($permissiontoadd) {
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=create"><i class="fa fa-plus"></i> '.$langs->trans('AddFirstTool').'</a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
}
|
|
|
|
} // Ende elseif ($systemId > 0)
|
|
|
|
print '</div>'; // fichecenter
|
|
|
|
// Tooltip Container
|
|
print '<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>';
|
|
|
|
// JavaScript: Produkt-Autocomplete + Zubehör-AJAX
|
|
print '<script>
|
|
$(document).ready(function() {
|
|
var baseUrl = "'.dol_escape_js(dol_buildpath('/kundenkarte', 1)).'";
|
|
|
|
// Produkt-Zeile ein-/ausblenden je nach Typ-Flag has_product
|
|
var $typeSelect = $("#select_type");
|
|
function updateProductRow() {
|
|
var $selected = $typeSelect.find("option:selected");
|
|
var hasProduct = $selected.data("has-product");
|
|
if (hasProduct == 1) {
|
|
$("#row_product").show();
|
|
} else {
|
|
$("#row_product").hide();
|
|
$("#fk_product").val("");
|
|
$("#product_search").val("");
|
|
}
|
|
}
|
|
$typeSelect.on("change", updateProductRow);
|
|
updateProductRow(); // Initial
|
|
|
|
// Produkt-Autocomplete
|
|
function initProductAutocomplete(inputSelector, hiddenSelector) {
|
|
var $input = $(inputSelector);
|
|
var $hidden = $(hiddenSelector);
|
|
if (!$input.length) return;
|
|
|
|
var searchTimeout;
|
|
$input.on("input", function() {
|
|
clearTimeout(searchTimeout);
|
|
var term = $(this).val();
|
|
if (term.length < 2) {
|
|
$hidden.val("");
|
|
$(".product-autocomplete-dropdown").remove();
|
|
return;
|
|
}
|
|
searchTimeout = setTimeout(function() {
|
|
$.get(baseUrl + "/ajax/equipment.php", {
|
|
action: "get_products",
|
|
term: term,
|
|
token: $("input[name=token]").val() || ""
|
|
}, function(data) {
|
|
$(".product-autocomplete-dropdown").remove();
|
|
if (data.success && data.products && data.products.length > 0) {
|
|
var $dropdown = $("<div class=\"product-autocomplete-dropdown\"></div>");
|
|
$.each(data.products, function(i, p) {
|
|
var label = p.ref + " - " + p.label;
|
|
if (p.price > 0) label += " (" + p.price + " €)";
|
|
$dropdown.append(
|
|
$("<div class=\"product-autocomplete-item\"></div>")
|
|
.text(label)
|
|
.data("id", p.id)
|
|
.data("ref", p.ref)
|
|
.data("label", p.label)
|
|
);
|
|
});
|
|
$input.after($dropdown);
|
|
$dropdown.on("click", ".product-autocomplete-item", function() {
|
|
var id = $(this).data("id");
|
|
var ref = $(this).data("ref");
|
|
var label = $(this).data("label");
|
|
$input.val(ref + " - " + label);
|
|
$hidden.val(id);
|
|
$dropdown.remove();
|
|
// Zubehör: Button aktivieren
|
|
if (inputSelector === "#accessory_product_search") {
|
|
$("#btn-add-accessory").prop("disabled", false);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}, 300);
|
|
});
|
|
|
|
// Dropdown schließen bei Klick außerhalb
|
|
$(document).on("click", function(e) {
|
|
if (!$(e.target).closest(inputSelector + ", .product-autocomplete-dropdown").length) {
|
|
$(".product-autocomplete-dropdown").remove();
|
|
}
|
|
});
|
|
|
|
// Bei manuellem Leeren auch Hidden zurücksetzen
|
|
$input.on("change", function() {
|
|
if (!$(this).val()) {
|
|
$hidden.val("");
|
|
if (inputSelector === "#accessory_product_search") {
|
|
$("#btn-add-accessory").prop("disabled", true);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
initProductAutocomplete("#product_search", "#fk_product");
|
|
initProductAutocomplete("#accessory_product_search", "#accessory_product_id");
|
|
|
|
// Zubehör hinzufügen
|
|
$("#btn-add-accessory").on("click", function() {
|
|
var productId = $("#accessory_product_id").val();
|
|
var qty = $("#accessory_qty").val() || 1;
|
|
var anlageId = '.((int) $anlageId).';
|
|
if (!productId || !anlageId) return;
|
|
|
|
$.post(baseUrl + "/ajax/anlage_accessory.php", {
|
|
action: "add",
|
|
fk_anlage: anlageId,
|
|
fk_product: productId,
|
|
qty: qty,
|
|
token: $("input[name=token]").val() || ""
|
|
}).done(function(data) {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert(data.error || "Fehler");
|
|
}
|
|
}).fail(function() {
|
|
alert("Server-Fehler");
|
|
});
|
|
});
|
|
|
|
// Zubehör löschen
|
|
$(".btn-delete-accessory").on("click", function(e) {
|
|
e.preventDefault();
|
|
if (!confirm("'.$langs->trans('ConfirmDeleteAccessory').'")) return;
|
|
var accId = $(this).data("id");
|
|
$.post(baseUrl + "/ajax/anlage_accessory.php", {
|
|
action: "delete",
|
|
id: accId,
|
|
token: $("input[name=token]").val() || ""
|
|
}).done(function(data) {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert(data.error || "Fehler");
|
|
}
|
|
});
|
|
});
|
|
|
|
// Lieferantenbestellung
|
|
$("#btn-order-accessories").on("click", function() {
|
|
var supplierId = $("#supplier_select").val();
|
|
var anlageId = '.((int) $anlageId).';
|
|
if (!supplierId) {
|
|
alert("Bitte Lieferant auswählen");
|
|
return;
|
|
}
|
|
|
|
// Alle Zubehör-IDs sammeln
|
|
var ids = [];
|
|
$(".btn-delete-accessory").each(function() {
|
|
ids.push($(this).data("id"));
|
|
});
|
|
if (ids.length === 0) return;
|
|
|
|
$.post(baseUrl + "/ajax/anlage_accessory.php", {
|
|
action: "order",
|
|
fk_anlage: anlageId,
|
|
supplier_id: supplierId,
|
|
"ids[]": ids,
|
|
token: $("input[name=token]").val() || ""
|
|
}).done(function(data) {
|
|
if (data.success && data.order_id) {
|
|
window.location.href = "'.DOL_URL_ROOT.'/fourn/commande/card.php?id=" + data.order_id;
|
|
} else {
|
|
alert(data.error || "Fehler beim Erstellen der Bestellung");
|
|
}
|
|
}).fail(function() {
|
|
alert("Server-Fehler");
|
|
});
|
|
});
|
|
});
|
|
</script>';
|
|
|
|
// CSS für Autocomplete
|
|
print '<style>
|
|
.product-autocomplete-dropdown {
|
|
position: absolute;
|
|
z-index: 1000;
|
|
background: var(--colorbackbody, #fff);
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
min-width: 300px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
}
|
|
.product-autocomplete-item {
|
|
padding: 8px 12px;
|
|
cursor: pointer;
|
|
border-bottom: 1px solid #333;
|
|
}
|
|
.product-autocomplete-item:hover {
|
|
background: var(--colorbacklinepairhover, #333);
|
|
}
|
|
.product-autocomplete-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
</style>';
|
|
|
|
llxFooter();
|
|
$db->close();
|
|
|
|
|
|
/**
|
|
* Baum rekursiv ausgeben (vereinfachte Version für Werkzeuge-Seite)
|
|
*/
|
|
function werkzeuge_printTree($nodes, $socid, $systemId, $canEdit, $canDelete, $langs, $level = 0, $typeFieldsMap = array())
|
|
{
|
|
foreach ($nodes as $node) {
|
|
$hasChildren = !empty($node->children);
|
|
$fieldValues = $node->getFieldValues();
|
|
|
|
// Badges sammeln
|
|
$treeInfoBadges = array();
|
|
$treeInfoParentheses = array();
|
|
|
|
if (!empty($typeFieldsMap[$node->fk_anlage_type])) {
|
|
foreach ($typeFieldsMap[$node->fk_anlage_type] as $fieldDef) {
|
|
if ($fieldDef->field_type === 'header') continue;
|
|
$value = isset($fieldValues[$fieldDef->field_code]) ? $fieldValues[$fieldDef->field_code] : '';
|
|
if ($fieldDef->show_in_tree && $value !== '') {
|
|
$displayVal = $value;
|
|
if ($fieldDef->field_type === 'date' && $value) {
|
|
$displayVal = dol_print_date(strtotime($value), 'day');
|
|
}
|
|
$fieldInfo = array(
|
|
'label' => $fieldDef->field_label,
|
|
'value' => $displayVal,
|
|
'code' => $fieldDef->field_code,
|
|
'type' => $fieldDef->field_type,
|
|
'color' => $fieldDef->badge_color ?? ''
|
|
);
|
|
$displayMode = $fieldDef->tree_display_mode ?? 'badge';
|
|
if ($displayMode === 'parentheses') {
|
|
$treeInfoParentheses[] = $fieldInfo;
|
|
} else {
|
|
$treeInfoBadges[] = $fieldInfo;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$nodeClass = 'kundenkarte-tree-node';
|
|
if (!empty($node->decommissioned)) {
|
|
$nodeClass .= ' decommissioned';
|
|
}
|
|
if ($node->type_can_have_children) {
|
|
$nodeClass .= ' node-structure';
|
|
} else {
|
|
$nodeClass .= ' node-leaf';
|
|
}
|
|
|
|
print '<div class="'.$nodeClass.'">';
|
|
print '<div class="kundenkarte-tree-item" data-anlage-id="'.$node->id.'">';
|
|
|
|
// Toggle
|
|
if ($hasChildren) {
|
|
print '<span class="kundenkarte-tree-toggle"><i class="fa fa-chevron-down"></i></span>';
|
|
} else {
|
|
print '<span class="kundenkarte-tree-toggle" style="visibility:hidden;"><i class="fa fa-chevron-down"></i></span>';
|
|
}
|
|
|
|
// Icon
|
|
$picto = $node->type_picto ? $node->type_picto : 'fa-wrench';
|
|
print '<span class="kundenkarte-tree-icon">'.kundenkarte_render_icon($picto).'</span>';
|
|
|
|
// Label
|
|
$viewUrl = $_SERVER['PHP_SELF'].'?system='.$systemId.'&action=view&anlage_id='.$node->id;
|
|
print '<span class="kundenkarte-tree-label">'.dol_escape_htmltag($node->label);
|
|
if (!empty($treeInfoParentheses)) {
|
|
$infoValues = array();
|
|
foreach ($treeInfoParentheses as $info) {
|
|
$infoValues[] = dol_escape_htmltag($info['value']);
|
|
}
|
|
print ' <span class="kundenkarte-tree-label-info">('.implode(', ', $infoValues).')</span>';
|
|
}
|
|
print '</span>';
|
|
|
|
// Ausgebaut-Badge
|
|
if (!empty($node->decommissioned)) {
|
|
$decommDate = !empty($node->date_decommissioned) ? dol_print_date(strtotime($node->date_decommissioned), 'day') : '';
|
|
$decommText = $langs->trans('Decommissioned');
|
|
if ($decommDate) $decommText .= ' '.$decommDate;
|
|
print ' <span class="badge-decommissioned"><i class="fa fa-power-off"></i> '.$decommText.'</span>';
|
|
}
|
|
|
|
// Produkt-Badge
|
|
if (!empty($node->fk_product) && !empty($node->product_ref)) {
|
|
print ' <span class="badge badge-secondary"><i class="fa fa-cube"></i> '.dol_escape_htmltag($node->product_ref).'</span>';
|
|
}
|
|
|
|
// Spacer
|
|
print '<span class="kundenkarte-tree-spacer"></span>';
|
|
|
|
// Badges
|
|
$defaultBadgeColor = getDolGlobalString('KUNDENKARTE_TREE_BADGE_COLOR', '#2a4a5e');
|
|
if (!empty($treeInfoBadges)) {
|
|
print '<span class="kundenkarte-tree-badges">';
|
|
foreach ($treeInfoBadges as $info) {
|
|
$badgeIcon = kundenkarte_get_field_icon($info['code'], $info['type']);
|
|
$fieldBadgeColor = !empty($info['color']) ? $info['color'] : $defaultBadgeColor;
|
|
print '<span class="kundenkarte-tree-badge" title="'.dol_escape_htmltag($info['label']).'" style="background:linear-gradient(135deg, '.$fieldBadgeColor.' 0%, '.kundenkarte_adjust_color($fieldBadgeColor, -20).' 100%);">';
|
|
print '<i class="fa '.$badgeIcon.'"></i> '.dol_escape_htmltag($info['value']);
|
|
print '</span>';
|
|
}
|
|
print '</span>';
|
|
}
|
|
|
|
// Typ-Badge
|
|
if ($node->type_short || $node->type_label) {
|
|
$typeDisplay = $node->type_short ? $node->type_short : $node->type_label;
|
|
print '<span class="kundenkarte-tree-type badge badge-secondary">'.dol_escape_htmltag($typeDisplay).'</span>';
|
|
}
|
|
|
|
// Aktionen
|
|
print '<span class="kundenkarte-tree-actions">';
|
|
print '<a href="'.$viewUrl.'" title="'.$langs->trans('View').'"><i class="fa fa-eye"></i></a>';
|
|
if ($canEdit) {
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=create&parent_id='.$node->id.'" title="'.$langs->trans('AddChild').'"><i class="fa fa-plus"></i></a>';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=edit&anlage_id='.$node->id.'" title="'.$langs->trans('Edit').'"><i class="fa fa-edit"></i></a>';
|
|
$decommLabel = $node->decommissioned ? $langs->trans('Recommission') : $langs->trans('Decommission');
|
|
$decommIcon = $node->decommissioned ? 'fa-plug' : 'fa-power-off';
|
|
print '<a href="#" class="btn-toggle-decommissioned" data-anlage-id="'.$node->id.'" title="'.$decommLabel.'"><i class="fa '.$decommIcon.'"></i></a>';
|
|
}
|
|
if ($canDelete) {
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?system='.$systemId.'&action=delete&anlage_id='.$node->id.'" title="'.$langs->trans('Delete').'" class="deletelink"><i class="fa fa-trash"></i></a>';
|
|
}
|
|
print '</span>';
|
|
|
|
print '</div>';
|
|
|
|
// Kinder
|
|
if ($hasChildren) {
|
|
print '<div class="kundenkarte-tree-children">';
|
|
werkzeuge_printTree($node->children, $socid, $systemId, $canEdit, $canDelete, $langs, $level + 1, $typeFieldsMap);
|
|
print '</div>';
|
|
}
|
|
|
|
print '</div>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Baum-Options für Select (vereinfacht)
|
|
*/
|
|
function werkzeuge_printTreeOptions($nodes, $selected = 0, $excludeId = 0, $prefix = '', $level = 0)
|
|
{
|
|
foreach ($nodes as $node) {
|
|
if ($node->id == $excludeId) continue;
|
|
$sel = ($node->id == $selected) ? ' selected' : '';
|
|
print '<option value="'.$node->id.'"'.$sel.'>'.$prefix.dol_escape_htmltag($node->label).'</option>';
|
|
if (!empty($node->children)) {
|
|
werkzeuge_printTreeOptions($node->children, $selected, $excludeId, $prefix.'── ', $level + 1);
|
|
}
|
|
}
|
|
}
|