- Virtuelle ID 99999999 statt $mysoc->id (ist immer 0 in Dolibarr) - Umbenennung "Firmen-Werkzeuge" → "Mein Betrieb" für mehrere Systeme - Unnötige Societe/Company-Includes entfernt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
830 lines
29 KiB
PHP
830 lines
29 KiB
PHP
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* Firmen-Werkzeuge: Baumansicht für eigene Maschinen und Werkzeuge
|
|
* System-Filter fix auf WERKZEUG
|
|
*/
|
|
|
|
// 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');
|
|
$anlageId = GETPOSTINT('anlage_id');
|
|
$parentId = GETPOSTINT('parent_id');
|
|
|
|
// Virtuelle Firma-ID für Werkzeuge - braucht keinen echten Societe-Eintrag
|
|
// Die Anlage-Tabelle verwendet diese ID nur als Gruppierung
|
|
$socId = 99999999;
|
|
|
|
// WERKZEUG-System ermitteln
|
|
$werkzeugSystemId = 0;
|
|
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system WHERE code = 'WERKZEUG' AND active = 1";
|
|
$resql = $db->query($sql);
|
|
if ($resql && $db->num_rows($resql) > 0) {
|
|
$obj = $db->fetch_object($resql);
|
|
$werkzeugSystemId = $obj->rowid;
|
|
}
|
|
|
|
if ($werkzeugSystemId <= 0) {
|
|
setEventMessages('System WERKZEUG nicht gefunden. Bitte Modul deaktivieren und wieder aktivieren.', null, 'errors');
|
|
llxHeader('', 'Firmen-Werkzeuge');
|
|
llxFooter();
|
|
exit;
|
|
}
|
|
|
|
$systemId = $werkzeugSystemId;
|
|
|
|
// Sicherstellen dass WERKZEUG für eigene Firma aktiviert ist
|
|
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."kundenkarte_societe_system";
|
|
$sql .= " WHERE fk_soc = ".((int) $socId)." AND fk_system = ".((int) $systemId);
|
|
$sql .= " AND (fk_contact IS NULL OR fk_contact = 0) AND active = 1";
|
|
$resql = $db->query($sql);
|
|
if (!$resql || $db->num_rows($resql) == 0) {
|
|
// Automatisch aktivieren
|
|
$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) $systemId).", NOW(), ".((int) $user->id).", 1)";
|
|
$db->query($sql);
|
|
}
|
|
|
|
// Objekte initialisieren
|
|
$form = new Form($db);
|
|
$anlage = new Anlage($db);
|
|
$anlageType = new AnlageType($db);
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
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']);
|
|
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']);
|
|
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ätigungsdialog
|
|
if ($action == 'delete') {
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?anlage_id='.$anlageId,
|
|
$langs->trans('DeleteElement'),
|
|
$langs->trans('ConfirmDeleteElement'),
|
|
'confirm_delete',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
// Typen für WERKZEUG-System laden
|
|
$types = $anlageType->fetchAllBySystem($systemId, 1, 1); // excludeGlobal=1, nur WERKZEUG-Typen
|
|
|
|
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
|
|
if ($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="background:#f0f0f0;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'].'?action=edit&anlage_id='.$anlageId.'">'.$langs->trans('Modify').'</a>';
|
|
}
|
|
if ($permissiontodelete) {
|
|
print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?action=delete&anlage_id='.$anlageId.'">'.$langs->trans('Delete').'</a>';
|
|
}
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'">'.$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'].'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="'.$formAction.'">';
|
|
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.'"'.$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
|
|
$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><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'].'">'.$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'].'?action=create">';
|
|
print '<i class="fa fa-plus"></i> '.$langs->trans('AddElement');
|
|
print '</a>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Steuerungs-Buttons
|
|
print '<div class="kundenkarte-tree-controls" style="margin-bottom:10px;">';
|
|
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>';
|
|
print '<button type="button" class="button small" id="btn-toggle-decommissioned" title="'.$langs->trans('ShowDecommissioned').'">';
|
|
print '<i class="fa fa-eye-slash"></i> <span>'.$langs->trans('Decommissioned').'</span>';
|
|
print '</button>';
|
|
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" 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'].'?action=create"><i class="fa fa-plus"></i> '.$langs->trans('AddFirstTool').'</a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
}
|
|
|
|
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-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'].'?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'].'?action=create&parent_id='.$node->id.'" title="'.$langs->trans('AddChild').'"><i class="fa fa-plus"></i></a>';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?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'].'?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);
|
|
}
|
|
}
|
|
}
|