feat: has_product Typ-Flag, Decommissioned-Default, Select2-Bugfix

- has_product Flag für Element- und Gebäudetypen im Admin-Center
- Migration v8.6.0: has_product Spalte in beide Typ-Tabellen
- Produkt-Zeile im Formular wird per JS je nach Typ ein-/ausgeblendet
- Admin-Setting KUNDENKARTE_SHOW_DECOMMISSIONED für Standard-Sichtbarkeit
- Toggle-Button + Tree-Klasse nutzen Admin-Default in allen 3 Ansichten
- Fix: Select2 Typ-Select behält Wert im Edit-Modus (trigger nach init)
- Fix: Fehlende color-Property in fetchAllBySystem() ergänzt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-03-03 21:21:38 +01:00
parent 3b9daeb238
commit c4338c8d7a
11 changed files with 162 additions and 43 deletions

View file

@ -64,6 +64,7 @@ if ($action == 'add') {
$anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml')); $anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml'));
$anlageType->can_have_equipment = GETPOSTINT('can_have_equipment'); $anlageType->can_have_equipment = GETPOSTINT('can_have_equipment');
$anlageType->has_accessories = GETPOSTINT('has_accessories'); $anlageType->has_accessories = GETPOSTINT('has_accessories');
$anlageType->has_product = GETPOSTINT('has_product');
$anlageType->picto = GETPOST('picto', 'alphanohtml'); $anlageType->picto = GETPOST('picto', 'alphanohtml');
$anlageType->color = GETPOST('color', 'alphanohtml'); $anlageType->color = GETPOST('color', 'alphanohtml');
$anlageType->position = GETPOSTINT('position'); $anlageType->position = GETPOSTINT('position');
@ -115,6 +116,7 @@ if ($action == 'update') {
$anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml')); $anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml'));
$anlageType->can_have_equipment = GETPOSTINT('can_have_equipment'); $anlageType->can_have_equipment = GETPOSTINT('can_have_equipment');
$anlageType->has_accessories = GETPOSTINT('has_accessories'); $anlageType->has_accessories = GETPOSTINT('has_accessories');
$anlageType->has_product = GETPOSTINT('has_product');
$anlageType->picto = GETPOST('picto', 'alphanohtml'); $anlageType->picto = GETPOST('picto', 'alphanohtml');
$anlageType->color = GETPOST('color', 'alphanohtml'); $anlageType->color = GETPOST('color', 'alphanohtml');
$anlageType->position = GETPOSTINT('position'); $anlageType->position = GETPOSTINT('position');
@ -169,6 +171,7 @@ if ($action == 'copy' && $typeId > 0) {
$newType->allowed_parent_types = $sourceType->allowed_parent_types; $newType->allowed_parent_types = $sourceType->allowed_parent_types;
$newType->can_have_equipment = $sourceType->can_have_equipment; $newType->can_have_equipment = $sourceType->can_have_equipment;
$newType->has_accessories = $sourceType->has_accessories; $newType->has_accessories = $sourceType->has_accessories;
$newType->has_product = $sourceType->has_product;
$newType->picto = $sourceType->picto; $newType->picto = $sourceType->picto;
$newType->color = $sourceType->color; $newType->color = $sourceType->color;
$newType->position = $sourceType->position + 1; $newType->position = $sourceType->position + 1;
@ -410,6 +413,11 @@ if (in_array($action, array('create', 'edit'))) {
print '<td><input type="checkbox" name="has_accessories" value="1"'.($anlageType->has_accessories ? ' checked' : '').'>'; print '<td><input type="checkbox" name="has_accessories" value="1"'.($anlageType->has_accessories ? ' checked' : '').'>';
print ' <span class="opacitymedium">('.$langs->trans('HasAccessoriesHelp').')</span></td></tr>'; print ' <span class="opacitymedium">('.$langs->trans('HasAccessoriesHelp').')</span></td></tr>';
// Produkt-Zuordnung erlauben
print '<tr><td>'.$langs->trans('HasProduct').'</td>';
print '<td><input type="checkbox" name="has_product" value="1"'.($anlageType->has_product ? ' checked' : '').'>';
print ' <span class="opacitymedium">('.$langs->trans('HasProductHelp').')</span></td></tr>';
// Allowed parent types - with multi-select UI // Allowed parent types - with multi-select UI
print '<tr><td>'.$langs->trans('AllowedParentTypes').'</td>'; print '<tr><td>'.$langs->trans('AllowedParentTypes').'</td>';
print '<td>'; print '<td>';

8
admin/building_types.php Executable file → Normal file
View file

@ -42,6 +42,7 @@ if ($action == 'add' && $user->admin) {
$buildingType->icon = GETPOST('icon', 'alphanohtml'); $buildingType->icon = GETPOST('icon', 'alphanohtml');
$buildingType->color = GETPOST('color', 'alphanohtml'); $buildingType->color = GETPOST('color', 'alphanohtml');
$buildingType->can_have_children = GETPOSTINT('can_have_children'); $buildingType->can_have_children = GETPOSTINT('can_have_children');
$buildingType->has_product = GETPOSTINT('has_product');
$buildingType->position = GETPOSTINT('position'); $buildingType->position = GETPOSTINT('position');
$buildingType->active = GETPOSTINT('active'); $buildingType->active = GETPOSTINT('active');
@ -82,6 +83,7 @@ if ($action == 'update' && $user->admin) {
$buildingType->icon = GETPOST('icon', 'alphanohtml'); $buildingType->icon = GETPOST('icon', 'alphanohtml');
$buildingType->color = GETPOST('color', 'alphanohtml'); $buildingType->color = GETPOST('color', 'alphanohtml');
$buildingType->can_have_children = GETPOSTINT('can_have_children'); $buildingType->can_have_children = GETPOSTINT('can_have_children');
$buildingType->has_product = GETPOSTINT('has_product');
$buildingType->position = GETPOSTINT('position'); $buildingType->position = GETPOSTINT('position');
$buildingType->active = GETPOSTINT('active'); $buildingType->active = GETPOSTINT('active');
@ -222,6 +224,12 @@ if ($action == 'create' || $action == 'edit') {
print '<input type="checkbox" name="can_have_children" value="1"'.($buildingType->can_have_children || $action != 'edit' ? ' checked' : '').'>'; print '<input type="checkbox" name="can_have_children" value="1"'.($buildingType->can_have_children || $action != 'edit' ? ' checked' : '').'>';
print '</td></tr>'; 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 // Position
print '<tr><td>'.$langs->trans('Position').'</td><td>'; print '<tr><td>'.$langs->trans('Position').'</td><td>';
$defaultPos = $action == 'create' ? $buildingType->getNextPosition() : $buildingType->position; $defaultPos = $action == 'create' ? $buildingType->getNextPosition() : $buildingType->position;

11
admin/setup.php Executable file → Normal file
View file

@ -125,6 +125,9 @@ if ($action == 'update') {
// View mode // View mode
dolibarr_set_const($db, 'KUNDENKARTE_DEFAULT_VIEW', GETPOST('KUNDENKARTE_DEFAULT_VIEW', 'aZ09'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, 'KUNDENKARTE_DEFAULT_VIEW', GETPOST('KUNDENKARTE_DEFAULT_VIEW', 'aZ09'), 'chaine', 0, '', $conf->entity);
// Ausgebaute Elemente standardmäßig anzeigen
dolibarr_set_const($db, 'KUNDENKARTE_SHOW_DECOMMISSIONED', GETPOSTINT('KUNDENKARTE_SHOW_DECOMMISSIONED'), 'chaine', 0, '', $conf->entity);
// Tree display settings // Tree display settings
dolibarr_set_const($db, 'KUNDENKARTE_TREE_INFO_DISPLAY', GETPOST('KUNDENKARTE_TREE_INFO_DISPLAY', 'aZ09'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, 'KUNDENKARTE_TREE_INFO_DISPLAY', GETPOST('KUNDENKARTE_TREE_INFO_DISPLAY', 'aZ09'), 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'KUNDENKARTE_TREE_BADGE_COLOR', GETPOST('KUNDENKARTE_TREE_BADGE_COLOR', 'alphanohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, 'KUNDENKARTE_TREE_BADGE_COLOR', GETPOST('KUNDENKARTE_TREE_BADGE_COLOR', 'alphanohtml'), 'chaine', 0, '', $conf->entity);
@ -207,6 +210,14 @@ print $form->selectarray('KUNDENKARTE_DEFAULT_VIEW', $viewModes, getDolGlobalStr
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
// Ausgebaute Elemente standardmäßig anzeigen
print '<tr class="oddeven">';
print '<td>'.$langs->trans("ShowDecommissionedDefault").'</td>';
print '<td>';
print $form->selectyesno('KUNDENKARTE_SHOW_DECOMMISSIONED', getDolGlobalInt('KUNDENKARTE_SHOW_DECOMMISSIONED', 0), 1);
print '</td>';
print '</tr>';
print '</table>'; print '</table>';
// Tree Display Settings // Tree Display Settings

View file

@ -27,6 +27,7 @@ class AnlageType extends CommonObject
public $allowed_parent_types; public $allowed_parent_types;
public $can_have_equipment; public $can_have_equipment;
public $has_accessories; public $has_accessories;
public $has_product;
public $picto; public $picto;
public $color; public $color;
@ -74,7 +75,7 @@ class AnlageType extends CommonObject
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql .= "entity, ref, label, label_short, description, fk_system,"; $sql .= "entity, ref, label, label_short, description, fk_system,";
$sql .= " can_have_children, can_be_nested, allowed_parent_types, can_have_equipment, has_accessories,"; $sql .= " can_have_children, can_be_nested, allowed_parent_types, can_have_equipment, has_accessories, has_product,";
$sql .= " picto, color, is_system, position, active,"; $sql .= " picto, color, is_system, position, active,";
$sql .= " date_creation, fk_user_creat"; $sql .= " date_creation, fk_user_creat";
$sql .= ") VALUES ("; $sql .= ") VALUES (";
@ -89,6 +90,7 @@ class AnlageType extends CommonObject
$sql .= ", ".($this->allowed_parent_types ? "'".$this->db->escape($this->allowed_parent_types)."'" : "NULL"); $sql .= ", ".($this->allowed_parent_types ? "'".$this->db->escape($this->allowed_parent_types)."'" : "NULL");
$sql .= ", ".((int) $this->can_have_equipment); $sql .= ", ".((int) $this->can_have_equipment);
$sql .= ", ".((int) $this->has_accessories); $sql .= ", ".((int) $this->has_accessories);
$sql .= ", ".((int) $this->has_product);
$sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL"); $sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
$sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL"); $sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
$sql .= ", 0"; // is_system = 0 for user-created $sql .= ", 0"; // is_system = 0 for user-created
@ -147,6 +149,7 @@ class AnlageType extends CommonObject
$this->allowed_parent_types = $obj->allowed_parent_types; $this->allowed_parent_types = $obj->allowed_parent_types;
$this->can_have_equipment = $obj->can_have_equipment ?? 0; $this->can_have_equipment = $obj->can_have_equipment ?? 0;
$this->has_accessories = $obj->has_accessories ?? 0; $this->has_accessories = $obj->has_accessories ?? 0;
$this->has_product = $obj->has_product ?? 0;
$this->picto = $obj->picto; $this->picto = $obj->picto;
$this->color = $obj->color; $this->color = $obj->color;
$this->is_system = $obj->is_system; $this->is_system = $obj->is_system;
@ -194,6 +197,7 @@ class AnlageType extends CommonObject
$sql .= ", allowed_parent_types = ".($this->allowed_parent_types ? "'".$this->db->escape($this->allowed_parent_types)."'" : "NULL"); $sql .= ", allowed_parent_types = ".($this->allowed_parent_types ? "'".$this->db->escape($this->allowed_parent_types)."'" : "NULL");
$sql .= ", can_have_equipment = ".((int) $this->can_have_equipment); $sql .= ", can_have_equipment = ".((int) $this->can_have_equipment);
$sql .= ", has_accessories = ".((int) $this->has_accessories); $sql .= ", has_accessories = ".((int) $this->has_accessories);
$sql .= ", has_product = ".((int) $this->has_product);
$sql .= ", picto = ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL"); $sql .= ", picto = ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL"); $sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
$sql .= ", position = ".((int) $this->position); $sql .= ", position = ".((int) $this->position);
@ -317,7 +321,9 @@ class AnlageType extends CommonObject
$type->allowed_parent_types = $obj->allowed_parent_types; $type->allowed_parent_types = $obj->allowed_parent_types;
$type->can_have_equipment = $obj->can_have_equipment ?? 0; $type->can_have_equipment = $obj->can_have_equipment ?? 0;
$type->has_accessories = $obj->has_accessories ?? 0; $type->has_accessories = $obj->has_accessories ?? 0;
$type->has_product = $obj->has_product ?? 0;
$type->picto = $obj->picto; $type->picto = $obj->picto;
$type->color = $obj->color;
$type->is_system = $obj->is_system; $type->is_system = $obj->is_system;
$type->position = $obj->position; $type->position = $obj->position;
$type->active = $obj->active; $type->active = $obj->active;

7
class/buildingtype.class.php Executable file → Normal file
View file

@ -33,6 +33,7 @@ class BuildingType extends CommonObject
public $picto; public $picto;
public $is_system; public $is_system;
public $can_have_children; public $can_have_children;
public $has_product;
public $position; public $position;
public $active; public $active;
public $date_creation; public $date_creation;
@ -69,7 +70,7 @@ class BuildingType extends CommonObject
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql .= "entity, ref, label, label_short, description, fk_parent, level_type,"; $sql .= "entity, ref, label, label_short, description, fk_parent, level_type,";
$sql .= "icon, color, picto, is_system, can_have_children, position, active,"; $sql .= "icon, color, picto, is_system, can_have_children, has_product, position, active,";
$sql .= "date_creation, fk_user_creat"; $sql .= "date_creation, fk_user_creat";
$sql .= ") VALUES ("; $sql .= ") VALUES (";
$sql .= (int)$conf->entity; $sql .= (int)$conf->entity;
@ -84,6 +85,7 @@ class BuildingType extends CommonObject
$sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL"); $sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
$sql .= ", ".(int)($this->is_system ?: 0); $sql .= ", ".(int)($this->is_system ?: 0);
$sql .= ", ".(int)($this->can_have_children !== null ? $this->can_have_children : 1); $sql .= ", ".(int)($this->can_have_children !== null ? $this->can_have_children : 1);
$sql .= ", ".(int)($this->has_product ?: 0);
$sql .= ", ".(int)($this->position ?: 0); $sql .= ", ".(int)($this->position ?: 0);
$sql .= ", ".(int)($this->active !== null ? $this->active : 1); $sql .= ", ".(int)($this->active !== null ? $this->active : 1);
$sql .= ", '".$this->db->idate($now)."'"; $sql .= ", '".$this->db->idate($now)."'";
@ -135,6 +137,7 @@ class BuildingType extends CommonObject
$this->picto = $obj->picto; $this->picto = $obj->picto;
$this->is_system = $obj->is_system; $this->is_system = $obj->is_system;
$this->can_have_children = $obj->can_have_children; $this->can_have_children = $obj->can_have_children;
$this->has_product = $obj->has_product ?? 0;
$this->position = $obj->position; $this->position = $obj->position;
$this->active = $obj->active; $this->active = $obj->active;
$this->date_creation = $this->db->jdate($obj->date_creation); $this->date_creation = $this->db->jdate($obj->date_creation);
@ -171,6 +174,7 @@ class BuildingType extends CommonObject
$sql .= ", icon = ".($this->icon ? "'".$this->db->escape($this->icon)."'" : "NULL"); $sql .= ", icon = ".($this->icon ? "'".$this->db->escape($this->icon)."'" : "NULL");
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL"); $sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
$sql .= ", can_have_children = ".(int)$this->can_have_children; $sql .= ", can_have_children = ".(int)$this->can_have_children;
$sql .= ", has_product = ".(int)($this->has_product ?: 0);
$sql .= ", position = ".(int)$this->position; $sql .= ", position = ".(int)$this->position;
$sql .= ", active = ".(int)$this->active; $sql .= ", active = ".(int)$this->active;
$sql .= ", fk_user_modif = ".(int)$user->id; $sql .= ", fk_user_modif = ".(int)$user->id;
@ -265,6 +269,7 @@ class BuildingType extends CommonObject
$type->picto = $obj->picto; $type->picto = $obj->picto;
$type->is_system = $obj->is_system; $type->is_system = $obj->is_system;
$type->can_have_children = $obj->can_have_children; $type->can_have_children = $obj->can_have_children;
$type->has_product = $obj->has_product ?? 0;
$type->position = $obj->position; $type->position = $obj->position;
$type->active = $obj->active; $type->active = $obj->active;
$type->parent_label = $obj->parent_label; $type->parent_label = $obj->parent_label;

View file

@ -76,7 +76,7 @@ class modKundenKarte extends DolibarrModules
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@kundenkarte' $this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@kundenkarte'
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
$this->version = '8.5'; $this->version = '8.6';
// Url to the file with your last numberversion of this module // Url to the file with your last numberversion of this module
//$this->url_last_version = 'http://www.example.com/versionmodule.txt'; //$this->url_last_version = 'http://www.example.com/versionmodule.txt';
@ -656,6 +656,9 @@ class modKundenKarte extends DolibarrModules
// v8.1.0: Werkzeuge & Zubehör // v8.1.0: Werkzeuge & Zubehör
$this->migrate_v810_werkzeuge(); $this->migrate_v810_werkzeuge();
// v8.6.0: has_product Flag für Typen
$this->migrate_v860_has_product();
} }
/** /**
@ -1022,6 +1025,29 @@ class modKundenKarte extends DolibarrModules
} }
} }
/**
* Migration v8.6.0: has_product Flag für Element-Typen und Gebäude-Typen
*/
private function migrate_v860_has_product()
{
// 1. has_product auf Element-Typ
$table = MAIN_DB_PREFIX."kundenkarte_anlage_type";
$resql = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'has_product'");
if (!$resql || $this->db->num_rows($resql) == 0) {
$this->db->query("ALTER TABLE ".$table." ADD COLUMN has_product tinyint DEFAULT 0 NOT NULL AFTER has_accessories");
}
// 2. has_product auf Gebäude-Typ
$table = MAIN_DB_PREFIX."kundenkarte_building_type";
$resql = $this->db->query("SHOW TABLES LIKE '".$this->db->escape($table)."'");
if ($resql && $this->db->num_rows($resql) > 0) {
$resql2 = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'has_product'");
if (!$resql2 || $this->db->num_rows($resql2) == 0) {
$this->db->query("ALTER TABLE ".$table." ADD COLUMN has_product tinyint DEFAULT 0 NOT NULL AFTER can_have_children");
}
}
}
/** /**
* Function called when module is disabled. * Function called when module is disabled.
* Remove from database constants, boxes and permissions from Dolibarr database. * Remove from database constants, boxes and permissions from Dolibarr database.

View file

@ -561,11 +561,14 @@ Decommissioned = Ausgebaut
Decommission = Ausbauen Decommission = Ausbauen
Recommission = Wieder einbauen Recommission = Wieder einbauen
ShowDecommissioned = Ausgebaute Elemente anzeigen ShowDecommissioned = Ausgebaute Elemente anzeigen
ShowDecommissionedDefault = Ausgebaute Elemente standardmäßig anzeigen
# Eigener Betrieb & Zubehör # Eigener Betrieb & Zubehör
CompanyTools = Mein Betrieb CompanyTools = Mein Betrieb
HasAccessories = Hat Zubehör HasAccessories = Hat Zubehör
HasAccessoriesHelp = Ermöglicht die Zuordnung von Zubehör und Ersatzteilen HasAccessoriesHelp = Ermöglicht die Zuordnung von Zubehör und Ersatzteilen
HasProduct = Produkt-Zuordnung
HasProductHelp = Ermöglicht die Verknüpfung mit einem Dolibarr-Produkt
Accessories = Zubehör / Ersatzteile Accessories = Zubehör / Ersatzteile
NoAccessories = Kein Zubehör zugeordnet NoAccessories = Kein Zubehör zugeordnet
SearchProduct = Produkt suchen SearchProduct = Produkt suchen

View file

@ -309,11 +309,14 @@ Decommissioned = Decommissioned
Decommission = Decommission Decommission = Decommission
Recommission = Recommission Recommission = Recommission
ShowDecommissioned = Show decommissioned elements ShowDecommissioned = Show decommissioned elements
ShowDecommissionedDefault = Show decommissioned elements by default
# Own Company & Accessories # Own Company & Accessories
CompanyTools = My Company CompanyTools = My Company
HasAccessories = Has Accessories HasAccessories = Has Accessories
HasAccessoriesHelp = Allows assigning accessories and spare parts HasAccessoriesHelp = Allows assigning accessories and spare parts
HasProduct = Product Assignment
HasProductHelp = Allows linking to a Dolibarr product
Accessories = Accessories / Spare Parts Accessories = Accessories / Spare Parts
NoAccessories = No accessories assigned NoAccessories = No accessories assigned
SearchProduct = Search product SearchProduct = Search product

View file

@ -510,8 +510,9 @@ if ($isTreeView) {
print '<button type="button" class="button small" id="btn-collapse-all" title="'.$langs->trans('CollapseAll').'">'; 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 '<i class="fa fa-compress"></i> '.$langs->trans('CollapseAll');
print '</button>'; print '</button>';
print '<button type="button" class="button small" id="btn-toggle-decommissioned" title="'.$langs->trans('ShowDecommissioned').'">'; $showDecomm = getDolGlobalInt('KUNDENKARTE_SHOW_DECOMMISSIONED', 0);
print '<i class="fa fa-eye-slash"></i> <span>'.$langs->trans('Decommissioned').'</span>'; 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 '</button>';
if ($systemId > 0) { if ($systemId > 0) {
$exportUrl = dol_buildpath('/kundenkarte/ajax/export_tree_pdf.php', 1).'?socid='.$id.'&system='.$systemId; $exportUrl = dol_buildpath('/kundenkarte/ajax/export_tree_pdf.php', 1).'?socid='.$id.'&system='.$systemId;
@ -593,8 +594,8 @@ if (empty($customerSystems)) {
print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>'; print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>';
print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>'; print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>';
// Zugeordnetes Produkt // Zugeordnetes Produkt (nur wenn Typ es erlaubt)
if ($anlage->fk_product > 0) { if ($type->has_product && $anlage->fk_product > 0) {
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
$product = new Product($db); $product = new Product($db);
if ($product->fetch($anlage->fk_product) > 0) { if ($product->fetch($anlage->fk_product) > 0) {
@ -983,7 +984,7 @@ if (empty($customerSystems)) {
$selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : ''; $selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
$picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : ''; $picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : '';
$color = !empty($t->color) ? dol_escape_htmltag($t->color) : ''; $color = !empty($t->color) ? dol_escape_htmltag($t->color) : '';
print '<option value="'.$t->id.'" data-category="building" data-icon="'.$picto.'" data-color="'.$color.'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>'; print '<option value="'.$t->id.'" data-category="building" data-icon="'.$picto.'" data-color="'.$color.'" data-has-product="'.($t->has_product ? '1' : '0').'" data-has-accessories="'.($t->has_accessories ? '1' : '0').'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>';
} }
if ($lastGroup !== '') print '</optgroup>'; if ($lastGroup !== '') print '</optgroup>';
} }
@ -995,7 +996,7 @@ if (empty($customerSystems)) {
$selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : ''; $selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
$picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : ''; $picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : '';
$color = !empty($t->color) ? dol_escape_htmltag($t->color) : ''; $color = !empty($t->color) ? dol_escape_htmltag($t->color) : '';
print '<option value="'.$t->id.'" data-category="element" data-icon="'.$picto.'" data-color="'.$color.'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>'; print '<option value="'.$t->id.'" data-category="element" data-icon="'.$picto.'" data-color="'.$color.'" data-has-product="'.($t->has_product ? '1' : '0').'" data-has-accessories="'.($t->has_accessories ? '1' : '0').'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>';
} }
print '</optgroup>'; print '</optgroup>';
} }
@ -1016,7 +1017,7 @@ if (empty($customerSystems)) {
printTreeOptions($tree, $selectedParent, $excludeId); printTreeOptions($tree, $selectedParent, $excludeId);
print '</select></td></tr>'; print '</select></td></tr>';
// Produkt-Zuordnung // Produkt-Zuordnung (wird per JS ein-/ausgeblendet je nach Typ)
$productValue = ''; $productValue = '';
$productId = 0; $productId = 0;
if (($isEdit || $isCopy) && $anlage->fk_product > 0) { if (($isEdit || $isCopy) && $anlage->fk_product > 0) {
@ -1027,7 +1028,7 @@ if (empty($customerSystems)) {
$productId = $product->id; $productId = $product->id;
} }
} }
print '<tr><td>'.$langs->trans('Product').'</td>'; print '<tr id="row_product" style="display:none;"><td>'.$langs->trans('Product').'</td>';
print '<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="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 '<input type="hidden" name="fk_product" id="fk_product" value="'.$productId.'">';
@ -1122,15 +1123,15 @@ if (empty($customerSystems)) {
$typeSelect.prop("disabled", false); $typeSelect.prop("disabled", false);
$("#row_type").show(); $("#row_type").show();
// Wert wiederherstellen falls noch vorhanden
if (currentVal && $typeSelect.find("option[value=\"" + currentVal + "\"]").length) {
$typeSelect.val(currentVal);
} else {
$typeSelect.val("");
}
// Select2 neu initialisieren // Select2 neu initialisieren
initSelect2(); initSelect2();
// Wert wiederherstellen falls noch vorhanden (nach Select2-Init mit trigger)
if (currentVal && $typeSelect.find("option[value=\"" + currentVal + "\"]").length) {
$typeSelect.val(currentVal).trigger("change");
} else {
$typeSelect.val("").trigger("change");
}
} }
$catSelect.on("change", function() { $catSelect.on("change", function() {
@ -1139,9 +1140,24 @@ if (empty($customerSystems)) {
$typeSelect.trigger("change"); $typeSelect.trigger("change");
}); });
// Produkt-Zeile ein-/ausblenden je nach Typ-Flag has_product
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);
// Initial filtern // Initial filtern
if ($catSelect.val()) { if ($catSelect.val()) {
filterTypes(); filterTypes();
updateProductRow();
} else { } else {
$typeSelect.prop("disabled", true); $typeSelect.prop("disabled", true);
$("#row_type").hide(); $("#row_type").hide();
@ -1209,7 +1225,7 @@ if (empty($customerSystems)) {
$connectionsByTarget = array(); $connectionsByTarget = array();
if (!empty($tree)) { if (!empty($tree)) {
print '<div class="kundenkarte-tree" data-system="'.$systemId.'" data-socid="'.$id.'">'; print '<div class="kundenkarte-tree'.($showDecomm ? ' show-decommissioned' : '').'" data-system="'.$systemId.'" data-socid="'.$id.'">';
printTree($tree, $id, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap, $connectionsByTarget); printTree($tree, $id, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap, $connectionsByTarget);
print '</div>'; print '</div>';
} else { } else {

View file

@ -508,8 +508,9 @@ if ($isTreeView) {
print '<button type="button" class="button small" id="btn-collapse-all" title="'.$langs->trans('CollapseAll').'">'; 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 '<i class="fa fa-compress"></i> '.$langs->trans('CollapseAll');
print '</button>'; print '</button>';
print '<button type="button" class="button small" id="btn-toggle-decommissioned" title="'.$langs->trans('ShowDecommissioned').'">'; $showDecomm = getDolGlobalInt('KUNDENKARTE_SHOW_DECOMMISSIONED', 0);
print '<i class="fa fa-eye-slash"></i> <span>'.$langs->trans('Decommissioned').'</span>'; 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 '</button>';
if ($systemId > 0) { if ($systemId > 0) {
$exportUrl = dol_buildpath('/kundenkarte/ajax/export_tree_pdf.php', 1).'?socid='.$object->socid.'&contactid='.$id.'&system='.$systemId; $exportUrl = dol_buildpath('/kundenkarte/ajax/export_tree_pdf.php', 1).'?socid='.$object->socid.'&contactid='.$id.'&system='.$systemId;
@ -591,8 +592,8 @@ if (empty($customerSystems)) {
print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>'; print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>';
print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>'; print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>';
// Zugeordnetes Produkt // Zugeordnetes Produkt (nur wenn Typ es erlaubt)
if ($anlage->fk_product > 0) { if ($type->has_product && $anlage->fk_product > 0) {
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
$product = new Product($db); $product = new Product($db);
if ($product->fetch($anlage->fk_product) > 0) { if ($product->fetch($anlage->fk_product) > 0) {
@ -979,7 +980,7 @@ if (empty($customerSystems)) {
$selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : ''; $selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
$picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : ''; $picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : '';
$color = !empty($t->color) ? dol_escape_htmltag($t->color) : ''; $color = !empty($t->color) ? dol_escape_htmltag($t->color) : '';
print '<option value="'.$t->id.'" data-category="building" data-icon="'.$picto.'" data-color="'.$color.'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>'; print '<option value="'.$t->id.'" data-category="building" data-icon="'.$picto.'" data-color="'.$color.'" data-has-product="'.($t->has_product ? '1' : '0').'" data-has-accessories="'.($t->has_accessories ? '1' : '0').'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>';
} }
if ($lastGroup !== '') print '</optgroup>'; if ($lastGroup !== '') print '</optgroup>';
} }
@ -991,7 +992,7 @@ if (empty($customerSystems)) {
$selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : ''; $selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
$picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : ''; $picto = !empty($t->picto) ? dol_escape_htmltag($t->picto) : '';
$color = !empty($t->color) ? dol_escape_htmltag($t->color) : ''; $color = !empty($t->color) ? dol_escape_htmltag($t->color) : '';
print '<option value="'.$t->id.'" data-category="element" data-icon="'.$picto.'" data-color="'.$color.'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>'; print '<option value="'.$t->id.'" data-category="element" data-icon="'.$picto.'" data-color="'.$color.'" data-has-product="'.($t->has_product ? '1' : '0').'" data-has-accessories="'.($t->has_accessories ? '1' : '0').'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>';
} }
print '</optgroup>'; print '</optgroup>';
} }
@ -1012,7 +1013,7 @@ if (empty($customerSystems)) {
printTreeOptions($tree, $selectedParent, $excludeId); printTreeOptions($tree, $selectedParent, $excludeId);
print '</select></td></tr>'; print '</select></td></tr>';
// Produkt-Zuordnung // Produkt-Zuordnung (wird per JS ein-/ausgeblendet je nach Typ)
$productValue = ''; $productValue = '';
$productId = 0; $productId = 0;
if (($isEdit || $isCopy) && $anlage->fk_product > 0) { if (($isEdit || $isCopy) && $anlage->fk_product > 0) {
@ -1023,7 +1024,7 @@ if (empty($customerSystems)) {
$productId = $product->id; $productId = $product->id;
} }
} }
print '<tr><td>'.$langs->trans('Product').'</td>'; print '<tr id="row_product" style="display:none;"><td>'.$langs->trans('Product').'</td>';
print '<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="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 '<input type="hidden" name="fk_product" id="fk_product" value="'.$productId.'">';
@ -1118,15 +1119,15 @@ if (empty($customerSystems)) {
$typeSelect.prop("disabled", false); $typeSelect.prop("disabled", false);
$("#row_type").show(); $("#row_type").show();
// Wert wiederherstellen falls noch vorhanden
if (currentVal && $typeSelect.find("option[value=\"" + currentVal + "\"]").length) {
$typeSelect.val(currentVal);
} else {
$typeSelect.val("");
}
// Select2 neu initialisieren // Select2 neu initialisieren
initSelect2(); initSelect2();
// Wert wiederherstellen falls noch vorhanden (nach Select2-Init mit trigger)
if (currentVal && $typeSelect.find("option[value=\"" + currentVal + "\"]").length) {
$typeSelect.val(currentVal).trigger("change");
} else {
$typeSelect.val("").trigger("change");
}
} }
$catSelect.on("change", function() { $catSelect.on("change", function() {
@ -1135,9 +1136,24 @@ if (empty($customerSystems)) {
$typeSelect.trigger("change"); $typeSelect.trigger("change");
}); });
// Produkt-Zeile ein-/ausblenden je nach Typ-Flag has_product
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);
// Initial filtern // Initial filtern
if ($catSelect.val()) { if ($catSelect.val()) {
filterTypes(); filterTypes();
updateProductRow();
} else { } else {
$typeSelect.prop("disabled", true); $typeSelect.prop("disabled", true);
$("#row_type").hide(); $("#row_type").hide();
@ -1205,7 +1221,7 @@ if (empty($customerSystems)) {
$connectionsByTarget = array(); $connectionsByTarget = array();
if (!empty($tree)) { if (!empty($tree)) {
print '<div class="kundenkarte-tree" data-system="'.$systemId.'" data-socid="'.$object->socid.'">'; print '<div class="kundenkarte-tree'.($showDecomm ? ' show-decommissioned' : '').'" data-system="'.$systemId.'" data-socid="'.$object->socid.'">';
printTree($tree, $id, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap, $connectionsByTarget); printTree($tree, $id, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap, $connectionsByTarget);
print '</div>'; print '</div>';
} else { } else {

View file

@ -296,8 +296,9 @@ if ($isTreeView && $systemId > 0) {
print '<button type="button" class="button small" id="btn-collapse-all" title="'.$langs->trans('CollapseAll').'">'; 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 '<i class="fa fa-compress"></i> '.$langs->trans('CollapseAll');
print '</button>'; print '</button>';
print '<button type="button" class="button small" id="btn-toggle-decommissioned" title="'.$langs->trans('ShowDecommissioned').'">'; $showDecomm = getDolGlobalInt('KUNDENKARTE_SHOW_DECOMMISSIONED', 0);
print '<i class="fa fa-eye-slash"></i> <span>'.$langs->trans('Decommissioned').'</span>'; 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 '</button>';
print '</div>'; print '</div>';
} }
@ -360,8 +361,8 @@ if (in_array($action, array('create', 'edit', 'view'))) {
print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>'; print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>';
print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>'; print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>';
// Zugeordnetes Produkt // Zugeordnetes Produkt (nur wenn Typ es erlaubt)
if ($anlage->fk_product > 0) { if ($type->has_product && $anlage->fk_product > 0) {
$product = new Product($db); $product = new Product($db);
if ($product->fetch($anlage->fk_product) > 0) { if ($product->fetch($anlage->fk_product) > 0) {
print '<tr><td>'.$langs->trans('Product').'</td>'; print '<tr><td>'.$langs->trans('Product').'</td>';
@ -519,7 +520,7 @@ if (in_array($action, array('create', 'edit', 'view'))) {
print '<option value="">'.$langs->trans('SelectType').'</option>'; print '<option value="">'.$langs->trans('SelectType').'</option>';
foreach ($types as $t) { foreach ($types as $t) {
$selected = ($isEdit && $anlage->fk_anlage_type == $t->id) ? ' selected' : ''; $selected = ($isEdit && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
print '<option value="'.$t->id.'"'.$selected.'>'.dol_escape_htmltag($t->label).'</option>'; 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>'; print '</select>';
if (empty($types)) { if (empty($types)) {
@ -537,7 +538,7 @@ if (in_array($action, array('create', 'edit', 'view'))) {
werkzeuge_printTreeOptions($tree, $selectedParent, $excludeId); werkzeuge_printTreeOptions($tree, $selectedParent, $excludeId);
print '</select></td></tr>'; print '</select></td></tr>';
// Produkt-Zuordnung // Produkt-Zuordnung (wird per JS ein-/ausgeblendet je nach Typ)
$productValue = ''; $productValue = '';
$productId = 0; $productId = 0;
if ($isEdit && $anlage->fk_product > 0) { if ($isEdit && $anlage->fk_product > 0) {
@ -548,7 +549,7 @@ if (in_array($action, array('create', 'edit', 'view'))) {
$productId = $product->id; $productId = $product->id;
} }
} }
print '<tr><td>'.$langs->trans('Product').'</td>'; print '<tr id="row_product" style="display:none;"><td>'.$langs->trans('Product').'</td>';
print '<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="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 '<input type="hidden" name="fk_product" id="fk_product" value="'.$productId.'">';
@ -603,7 +604,7 @@ if (in_array($action, array('create', 'edit', 'view'))) {
} }
if (!empty($tree)) { if (!empty($tree)) {
print '<div class="kundenkarte-tree" data-system="'.$systemId.'" data-socid="'.$socId.'">'; print '<div class="kundenkarte-tree'.($showDecomm ? ' show-decommissioned' : '').'" data-system="'.$systemId.'" data-socid="'.$socId.'">';
werkzeuge_printTree($tree, $socId, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap); werkzeuge_printTree($tree, $socId, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap);
print '</div>'; print '</div>';
} else { } else {
@ -629,6 +630,22 @@ print '<script>
$(document).ready(function() { $(document).ready(function() {
var baseUrl = "'.dol_escape_js(dol_buildpath('/kundenkarte', 1)).'"; 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 // Produkt-Autocomplete
function initProductAutocomplete(inputSelector, hiddenSelector) { function initProductAutocomplete(inputSelector, hiddenSelector) {
var $input = $(inputSelector); var $input = $(inputSelector);