diff --git a/admin/busbar_types.php b/admin/busbar_types.php
index d44d80e..ead72df 100644
--- a/admin/busbar_types.php
+++ b/admin/busbar_types.php
@@ -85,6 +85,12 @@ if ($action == 'add') {
$busbarType->description = GETPOST('description', 'restricthtml');
$busbarType->fk_system = GETPOSTINT('fk_system');
$busbarType->phases = GETPOST('phases', 'alphanohtml');
+ // Convert comma-separated phases_config to JSON array
+ $phasesConfigInput = GETPOST('phases_config', 'alphanohtml');
+ if (!empty($phasesConfigInput)) {
+ $arr = array_map('trim', explode(',', $phasesConfigInput));
+ $busbarType->phases_config = json_encode($arr);
+ }
$busbarType->num_lines = GETPOSTINT('num_lines');
$busbarType->color = GETPOST('color', 'alphanohtml');
$busbarType->default_color = GETPOST('default_color', 'alphanohtml');
@@ -120,6 +126,14 @@ if ($action == 'update') {
$busbarType->description = GETPOST('description', 'restricthtml');
$busbarType->fk_system = GETPOSTINT('fk_system');
$busbarType->phases = GETPOST('phases', 'alphanohtml');
+ // Convert comma-separated phases_config to JSON array
+ $phasesConfigInput = GETPOST('phases_config', 'alphanohtml');
+ if (!empty($phasesConfigInput)) {
+ $arr = array_map('trim', explode(',', $phasesConfigInput));
+ $busbarType->phases_config = json_encode($arr);
+ } else {
+ $busbarType->phases_config = null;
+ }
$busbarType->num_lines = GETPOSTINT('num_lines');
$busbarType->color = GETPOST('color', 'alphanohtml');
$busbarType->default_color = GETPOST('default_color', 'alphanohtml');
@@ -267,6 +281,20 @@ if ($action == 'create' || $action == 'edit') {
print '
| '.$langs->trans('Colors').' | ';
print '';
diff --git a/ajax/busbar_types.php b/ajax/busbar_types.php
new file mode 100644
index 0000000..6109464
--- /dev/null
+++ b/ajax/busbar_types.php
@@ -0,0 +1,71 @@
+loadLangs(array('kundenkarte@kundenkarte'));
+
+$action = GETPOST('action', 'aZ09');
+$systemId = GETPOSTINT('system_id');
+
+$response = array('success' => false, 'error' => '');
+
+// Security check
+if (!$user->hasRight('kundenkarte', 'read')) {
+ $response['error'] = $langs->trans('ErrorPermissionDenied');
+ echo json_encode($response);
+ exit;
+}
+
+$busbarType = new BusbarType($db);
+
+switch ($action) {
+ case 'list':
+ // Get all busbar types for a system (or all if system_id = 0)
+ $types = $busbarType->fetchAllBySystem($systemId, 1);
+
+ $result = array();
+ foreach ($types as $t) {
+ $result[] = array(
+ 'id' => $t->id,
+ 'ref' => $t->ref,
+ 'label' => $t->label,
+ 'label_short' => $t->label_short,
+ 'phases' => $t->phases,
+ 'phases_config' => $t->phases_config ? json_decode($t->phases_config, true) : null,
+ 'num_lines' => $t->num_lines,
+ 'color' => $t->color,
+ 'default_color' => $t->default_color,
+ 'line_height' => $t->line_height,
+ 'line_spacing' => $t->line_spacing,
+ 'position_default' => $t->position_default,
+ 'fk_system' => $t->fk_system,
+ 'system_label' => $t->system_label
+ );
+ }
+
+ $response['success'] = true;
+ $response['types'] = $result;
+ break;
+
+ default:
+ $response['error'] = 'Unknown action';
+ break;
+}
+
+echo json_encode($response);
diff --git a/ajax/equipment_connection.php b/ajax/equipment_connection.php
index fbeb776..91f5ff3 100644
--- a/ajax/equipment_connection.php
+++ b/ajax/equipment_connection.php
@@ -102,6 +102,8 @@ switch ($action) {
'rail_phases' => $c->rail_phases,
'excluded_te' => $c->excluded_te,
'position_y' => $c->position_y,
+ 'fk_busbar_type' => $c->fk_busbar_type,
+ 'phases_config' => $c->phases_config ? json_decode($c->phases_config, true) : null,
'display_label' => $c->getDisplayLabel()
);
}
@@ -196,6 +198,7 @@ switch ($action) {
if (GETPOSTISSET('position_y')) $connection->position_y = GETPOSTINT('position_y');
if (GETPOSTISSET('path_data')) $connection->path_data = GETPOST('path_data', 'nohtml');
if (GETPOSTISSET('bundled_terminals')) $connection->bundled_terminals = GETPOST('bundled_terminals', 'alphanohtml');
+ if (GETPOSTISSET('fk_busbar_type')) $connection->fk_busbar_type = GETPOSTINT('fk_busbar_type') ?: null;
$result = $connection->update($user);
if ($result > 0) {
@@ -239,6 +242,8 @@ switch ($action) {
$connection->rail_end_te = GETPOSTINT('rail_end_te');
$connection->rail_phases = GETPOST('rail_phases', 'alphanohtml');
$connection->excluded_te = GETPOST('excluded_te', 'alphanohtml');
+ $connection->num_lines = GETPOSTINT('num_lines') ?: 1;
+ $connection->fk_busbar_type = GETPOSTINT('fk_busbar_type') ?: null;
$connection->fk_carrier = $carrierId;
$connection->position_y = GETPOSTINT('position_y');
@@ -248,6 +253,7 @@ switch ($action) {
$response['connection_id'] = $result;
} else {
$response['error'] = $connection->error ?: 'Create failed';
+ $response['sql_errors'] = $connection->errors;
}
break;
@@ -368,6 +374,8 @@ switch ($action) {
'rail_start_te' => $obj->rail_start_te,
'rail_end_te' => $obj->rail_end_te,
'rail_phases' => $obj->rail_phases,
+ 'num_lines' => isset($obj->num_lines) ? $obj->num_lines : 1,
+ 'fk_busbar_type' => isset($obj->fk_busbar_type) ? $obj->fk_busbar_type : null,
'position_y' => $obj->position_y,
'fk_carrier' => $obj->fk_carrier,
'path_data' => isset($obj->path_data) ? $obj->path_data : null
diff --git a/class/busbartype.class.php b/class/busbartype.class.php
index 2c769ee..7d93508 100644
--- a/class/busbartype.class.php
+++ b/class/busbartype.class.php
@@ -24,6 +24,7 @@ class BusbarType extends CommonObject
// Busbar-spezifische Felder
public $phases; // Channel configuration (A, B, AB, ABC, or legacy L1, L2, L3, N, PE, etc.)
+ public $phases_config; // JSON array of phase labels per line, e.g. ["L1","L2","L3"]
public $num_lines = 1; // Anzahl der Linien
public $color; // Kommagetrennte Farben
public $default_color; // Standard-Einzelfarbe
@@ -80,7 +81,7 @@ class BusbarType extends CommonObject
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
$sql .= "entity, ref, label, label_short, description, fk_system,";
- $sql .= " phases, num_lines, color, default_color, line_height, line_spacing, position_default,";
+ $sql .= " phases, phases_config, num_lines, color, default_color, line_height, line_spacing, position_default,";
$sql .= " fk_product, picto, icon_file, is_system, position, active,";
$sql .= " date_creation, fk_user_creat";
$sql .= ") VALUES (";
@@ -91,6 +92,7 @@ class BusbarType extends CommonObject
$sql .= ", ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL");
$sql .= ", ".((int) $this->fk_system);
$sql .= ", '".$this->db->escape($this->phases)."'";
+ $sql .= ", ".($this->phases_config ? "'".$this->db->escape($this->phases_config)."'" : "NULL");
$sql .= ", ".((int) ($this->num_lines > 0 ? $this->num_lines : 1));
$sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
$sql .= ", ".($this->default_color ? "'".$this->db->escape($this->default_color)."'" : "NULL");
@@ -206,6 +208,7 @@ class BusbarType extends CommonObject
$sql .= ", description = ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL");
$sql .= ", fk_system = ".((int) $this->fk_system);
$sql .= ", phases = '".$this->db->escape($this->phases)."'";
+ $sql .= ", phases_config = ".($this->phases_config ? "'".$this->db->escape($this->phases_config)."'" : "NULL");
$sql .= ", num_lines = ".((int) ($this->num_lines > 0 ? $this->num_lines : 1));
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
$sql .= ", default_color = ".($this->default_color ? "'".$this->db->escape($this->default_color)."'" : "NULL");
@@ -316,6 +319,7 @@ class BusbarType extends CommonObject
$type->label_short = $obj->label_short;
$type->fk_system = $obj->fk_system;
$type->phases = $obj->phases;
+ $type->phases_config = $obj->phases_config;
$type->num_lines = $obj->num_lines;
$type->color = $obj->color;
$type->default_color = $obj->default_color;
diff --git a/class/equipmentconnection.class.php b/class/equipmentconnection.class.php
index b22924a..0326414 100644
--- a/class/equipmentconnection.class.php
+++ b/class/equipmentconnection.class.php
@@ -42,6 +42,9 @@ class EquipmentConnection extends CommonObject
public $rail_end_te;
public $rail_phases; // '3P', '3P+N', 'L1', 'L1N', etc.
public $excluded_te; // Comma-separated TE positions to exclude (gaps for FI)
+ public $num_lines = 1; // Number of lines for busbar (1-5)
+ public $fk_busbar_type; // Reference to busbar type template
+ public $phases_config; // JSON array of phase labels from busbar type
public $fk_carrier;
public $position_y = 0;
@@ -90,7 +93,7 @@ class EquipmentConnection extends CommonObject
$sql .= "entity, fk_source, source_terminal, source_terminal_id, bundled_terminals, fk_target, target_terminal, target_terminal_id,";
$sql .= " connection_type, color, output_label,";
$sql .= " medium_type, medium_spec, medium_length,";
- $sql .= " is_rail, rail_start_te, rail_end_te, rail_phases, excluded_te, fk_carrier, position_y, path_data,";
+ $sql .= " is_rail, rail_start_te, rail_end_te, rail_phases, excluded_te, num_lines, fk_busbar_type, fk_carrier, position_y, path_data,";
$sql .= " note_private, status, date_creation, fk_user_creat";
$sql .= ") VALUES (";
$sql .= ((int) $conf->entity);
@@ -112,6 +115,8 @@ class EquipmentConnection extends CommonObject
$sql .= ", ".($this->rail_end_te > 0 ? ((int) $this->rail_end_te) : "NULL");
$sql .= ", ".($this->rail_phases ? "'".$this->db->escape($this->rail_phases)."'" : "NULL");
$sql .= ", ".($this->excluded_te ? "'".$this->db->escape($this->excluded_te)."'" : "NULL");
+ $sql .= ", ".((int) ($this->num_lines > 0 ? $this->num_lines : 1));
+ $sql .= ", ".($this->fk_busbar_type > 0 ? ((int) $this->fk_busbar_type) : "NULL");
$sql .= ", ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
$sql .= ", ".((int) $this->position_y);
$sql .= ", ".($this->path_data ? "'".$this->db->escape($this->path_data)."'" : "NULL");
@@ -237,6 +242,7 @@ class EquipmentConnection extends CommonObject
$sql .= ", rail_end_te = ".($this->rail_end_te > 0 ? ((int) $this->rail_end_te) : "NULL");
$sql .= ", rail_phases = ".($this->rail_phases ? "'".$this->db->escape($this->rail_phases)."'" : "NULL");
$sql .= ", excluded_te = ".($this->excluded_te ? "'".$this->db->escape($this->excluded_te)."'" : "NULL");
+ $sql .= ", fk_busbar_type = ".($this->fk_busbar_type > 0 ? ((int) $this->fk_busbar_type) : "NULL");
$sql .= ", fk_carrier = ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
$sql .= ", position_y = ".((int) $this->position_y);
$sql .= ", path_data = ".($this->path_data ? "'".$this->db->escape($this->path_data)."'" : "NULL");
@@ -300,10 +306,12 @@ class EquipmentConnection extends CommonObject
$sql = "SELECT c.*, ";
$sql .= " src.label as source_label, src.position_te as source_pos, src.width_te as source_width,";
- $sql .= " tgt.label as target_label, tgt.position_te as target_pos";
+ $sql .= " tgt.label as target_label, tgt.position_te as target_pos,";
+ $sql .= " bt.phases_config as busbar_phases_config";
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as c";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment as src ON c.fk_source = src.rowid";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment as tgt ON c.fk_target = tgt.rowid";
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_busbar_type as bt ON c.fk_busbar_type = bt.rowid";
$sql .= " WHERE c.fk_carrier = ".((int) $carrierId);
if ($activeOnly) {
$sql .= " AND c.status = 1";
@@ -344,6 +352,8 @@ class EquipmentConnection extends CommonObject
$conn->source_width = $obj->source_width;
$conn->target_label = $obj->target_label;
$conn->target_pos = $obj->target_pos;
+ $conn->fk_busbar_type = isset($obj->fk_busbar_type) ? $obj->fk_busbar_type : null;
+ $conn->phases_config = isset($obj->busbar_phases_config) ? $obj->busbar_phases_config : null;
$results[] = $conn;
}
diff --git a/core/modules/modKundenKarte.class.php b/core/modules/modKundenKarte.class.php
index 101ca14..788a876 100644
--- a/core/modules/modKundenKarte.class.php
+++ b/core/modules/modKundenKarte.class.php
@@ -659,6 +659,9 @@ class modKundenKarte extends DolibarrModules
// v8.6.0: has_product Flag für Typen
$this->migrate_v860_has_product();
+
+ // v11.0.0: Busbar type reference and num_lines for connections
+ $this->migrate_v1100_busbar_fields();
}
/**
@@ -1048,6 +1051,48 @@ class modKundenKarte extends DolibarrModules
}
}
+ /**
+ * Migration v11.0.0: Add busbar type fields to connections
+ */
+ private function migrate_v1100_busbar_fields()
+ {
+ $table = MAIN_DB_PREFIX."kundenkarte_equipment_connection";
+
+ // Check if table exists
+ $resql = $this->db->query("SHOW TABLES LIKE '".$this->db->escape($table)."'");
+ if (!$resql || $this->db->num_rows($resql) == 0) {
+ return;
+ }
+
+ // Add num_lines column
+ $resql = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'num_lines'");
+ if (!$resql || $this->db->num_rows($resql) == 0) {
+ $this->db->query("ALTER TABLE ".$table." ADD COLUMN num_lines int(11) DEFAULT 1 AFTER excluded_te");
+ }
+
+ // Add fk_busbar_type column
+ $resql = $this->db->query("SHOW COLUMNS FROM ".$table." LIKE 'fk_busbar_type'");
+ if (!$resql || $this->db->num_rows($resql) == 0) {
+ $this->db->query("ALTER TABLE ".$table." ADD COLUMN fk_busbar_type int(11) DEFAULT NULL AFTER num_lines");
+ }
+
+ // Extend color column to support comma-separated colors for multi-line busbars
+ $resql = $this->db->query("SHOW COLUMNS FROM ".$table." WHERE Field = 'color' AND Type LIKE 'varchar(20)%'");
+ if ($resql && $this->db->num_rows($resql) > 0) {
+ $this->db->query("ALTER TABLE ".$table." MODIFY COLUMN color varchar(255)");
+ }
+
+ // Add phases_config column to busbar_type table
+ $busbarTable = MAIN_DB_PREFIX."kundenkarte_busbar_type";
+ $resql = $this->db->query("SHOW TABLES LIKE '".$this->db->escape($busbarTable)."'");
+ if ($resql && $this->db->num_rows($resql) > 0) {
+ $resql2 = $this->db->query("SHOW COLUMNS FROM ".$busbarTable." LIKE 'phases_config'");
+ if (!$resql2 || $this->db->num_rows($resql2) == 0) {
+ $this->db->query("ALTER TABLE ".$busbarTable." ADD COLUMN phases_config TEXT DEFAULT NULL AFTER phases");
+ }
+ }
+ }
+
/**
* Function called when module is disabled.
* Remove from database constants, boxes and permissions from Dolibarr database.
diff --git a/js/kundenkarte.js b/js/kundenkarte.js
index 0e0f32d..cde2100 100644
--- a/js/kundenkarte.js
+++ b/js/kundenkarte.js
@@ -5195,6 +5195,7 @@
equipment: [],
connections: [],
bridges: [], // Terminal bridges (Brücken zwischen Klemmen)
+ busbarTypes: [], // Sammelschienen-Typen aus Datenbank
selectedTerminal: null,
dragState: null,
isInitialized: false,
@@ -5276,6 +5277,30 @@
return '#f1c40f'; // Default yellow
},
+ // Parse phase configuration into repeating labels array
+ parsePhaseLabels: function(phases) {
+ if (!phases) return [];
+ var p = phases.toUpperCase();
+
+ // Common configurations
+ if (p === '3P' || p === 'L1L2L3') return ['L1', 'L2', 'L3'];
+ if (p === '3P+N' || p === '3PN') return ['L1', 'L2', 'L3', 'N'];
+ if (p === '3P+N+PE' || p === '3PNPE') return ['L1', 'L2', 'L3', 'N', 'PE'];
+ if (p === 'L1N' || p === 'L1+N') return ['L1', 'N'];
+ if (p === 'L1') return ['L1'];
+ if (p === 'L2') return ['L2'];
+ if (p === 'L3') return ['L3'];
+ if (p === 'N') return ['N'];
+ if (p === 'PE') return ['PE'];
+
+ // Try to split by + or comma
+ if (p.indexOf('+') !== -1) return p.split('+');
+ if (p.indexOf(',') !== -1) return p.split(',');
+
+ // Single phase/label
+ return [phases];
+ },
+
// Get connection color for a specific terminal (if connected)
getTerminalConnectionColor: function(equipmentId, terminalId) {
var eqId = String(equipmentId);
@@ -5479,10 +5504,31 @@
}
this.anlageId = anlageId;
this.loadDisplaySettings();
+ this.loadBusbarTypes();
this.bindEvents();
this.loadData();
},
+ // Load busbar types from database
+ loadBusbarTypes: function() {
+ var self = this;
+ $.ajax({
+ url: baseUrl + '/custom/kundenkarte/ajax/busbar_types.php',
+ data: { action: 'list', system_id: 0 }, // 0 = Alle Systeme
+ dataType: 'json',
+ async: false, // Synchron laden damit Typen sofort verfügbar sind
+ success: function(response) {
+ if (response.success && response.types) {
+ self.busbarTypes = response.types;
+ self.log('Loaded ' + self.busbarTypes.length + ' busbar types');
+ }
+ },
+ error: function() {
+ console.warn('Could not load busbar types');
+ }
+ });
+ },
+
bindEvents: function() {
var self = this;
@@ -6378,19 +6424,34 @@
var totalTE = carrier ? (parseFloat(carrier.total_te) || 12) : 12;
var html = '';
- html += '';
+ html += ' ';
html += ' Sammelschiene bearbeiten';
- // Phase type selection
- html += ' ';
- html += ' |