Neuer Editor neue Idee
This commit is contained in:
parent
658b2df045
commit
3de514308b
34 changed files with 11320 additions and 6 deletions
|
|
@ -52,6 +52,7 @@ if ($action == 'add') {
|
|||
$anlageType->can_have_children = GETPOSTINT('can_have_children');
|
||||
$anlageType->can_be_nested = GETPOSTINT('can_be_nested');
|
||||
$anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml'));
|
||||
$anlageType->can_have_equipment = GETPOSTINT('can_have_equipment');
|
||||
$anlageType->picto = GETPOST('picto', 'alphanohtml');
|
||||
$anlageType->color = GETPOST('color', 'alphanohtml');
|
||||
$anlageType->position = GETPOSTINT('position');
|
||||
|
|
@ -101,6 +102,7 @@ if ($action == 'update') {
|
|||
$anlageType->can_have_children = GETPOSTINT('can_have_children');
|
||||
$anlageType->can_be_nested = GETPOSTINT('can_be_nested');
|
||||
$anlageType->allowed_parent_types = preg_replace('/[^A-Z0-9_,]/i', '', GETPOST('allowed_parent_types', 'nohtml'));
|
||||
$anlageType->can_have_equipment = GETPOSTINT('can_have_equipment');
|
||||
$anlageType->picto = GETPOST('picto', 'alphanohtml');
|
||||
$anlageType->color = GETPOST('color', 'alphanohtml');
|
||||
$anlageType->position = GETPOSTINT('position');
|
||||
|
|
@ -153,6 +155,7 @@ if ($action == 'copy' && $typeId > 0) {
|
|||
$newType->can_have_children = $sourceType->can_have_children;
|
||||
$newType->can_be_nested = $sourceType->can_be_nested;
|
||||
$newType->allowed_parent_types = $sourceType->allowed_parent_types;
|
||||
$newType->can_have_equipment = $sourceType->can_have_equipment;
|
||||
$newType->picto = $sourceType->picto;
|
||||
$newType->color = $sourceType->color;
|
||||
$newType->position = $sourceType->position + 1;
|
||||
|
|
@ -361,6 +364,11 @@ if (in_array($action, array('create', 'edit'))) {
|
|||
print '<td><input type="checkbox" name="can_be_nested" value="1"'.($anlageType->can_be_nested ? ' checked' : '').'>';
|
||||
print ' <span class="opacitymedium">('.$langs->trans('SameTypeUnderItself').')</span></td></tr>';
|
||||
|
||||
// Can have equipment (Hutschienen-Komponenten)
|
||||
print '<tr><td>'.$langs->trans('CanHaveEquipment').'</td>';
|
||||
print '<td><input type="checkbox" name="can_have_equipment" value="1"'.($anlageType->can_have_equipment ? ' checked' : '').'>';
|
||||
print ' <span class="opacitymedium">('.$langs->trans('CanHaveEquipmentHelp').')</span></td></tr>';
|
||||
|
||||
// Allowed parent types - with multi-select UI
|
||||
print '<tr><td>'.$langs->trans('AllowedParentTypes').'</td>';
|
||||
print '<td>';
|
||||
|
|
|
|||
670
admin/equipment_types.php
Normal file
670
admin/equipment_types.php
Normal file
|
|
@ -0,0 +1,670 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* Admin page to manage equipment types (Hutschienen-Komponenten)
|
||||
*/
|
||||
|
||||
$res = 0;
|
||||
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
|
||||
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
|
||||
if (!$res) die("Include of main fails");
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
|
||||
dol_include_once('/kundenkarte/lib/kundenkarte.lib.php');
|
||||
dol_include_once('/kundenkarte/class/equipmenttype.class.php');
|
||||
|
||||
$langs->loadLangs(array('admin', 'kundenkarte@kundenkarte', 'products'));
|
||||
|
||||
// Security check
|
||||
if (!$user->admin && !$user->hasRight('kundenkarte', 'admin')) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$confirm = GETPOST('confirm', 'alpha');
|
||||
$typeId = GETPOSTINT('typeid');
|
||||
$systemFilter = GETPOSTINT('system');
|
||||
|
||||
$form = new Form($db);
|
||||
$equipmentType = new EquipmentType($db);
|
||||
|
||||
// Load systems
|
||||
$systems = array();
|
||||
$sql = "SELECT rowid, code, label 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)) {
|
||||
$systems[$obj->rowid] = $obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Load products for dropdown
|
||||
$products = array();
|
||||
$sql = "SELECT rowid, ref, label FROM ".MAIN_DB_PREFIX."product WHERE tosell = 1 ORDER BY ref ASC";
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $db->fetch_object($resql)) {
|
||||
$products[$obj->rowid] = $obj;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Actions
|
||||
*/
|
||||
|
||||
if ($action == 'add') {
|
||||
$equipmentType->ref = GETPOST('ref', 'aZ09');
|
||||
$equipmentType->label = GETPOST('label', 'alphanohtml');
|
||||
$equipmentType->label_short = GETPOST('label_short', 'alphanohtml');
|
||||
$equipmentType->description = GETPOST('description', 'restricthtml');
|
||||
$equipmentType->fk_system = GETPOSTINT('fk_system');
|
||||
$equipmentType->width_te = GETPOSTINT('width_te');
|
||||
$equipmentType->color = GETPOST('color', 'alphanohtml');
|
||||
$equipmentType->fk_product = GETPOSTINT('fk_product');
|
||||
$equipmentType->terminals_config = GETPOST('terminals_config', 'nohtml');
|
||||
$equipmentType->picto = GETPOST('picto', 'alphanohtml');
|
||||
$equipmentType->position = GETPOSTINT('position');
|
||||
$equipmentType->active = 1;
|
||||
|
||||
if (empty($equipmentType->ref) || empty($equipmentType->label) || empty($equipmentType->fk_system)) {
|
||||
setEventMessages($langs->trans('ErrorFieldRequired'), null, 'errors');
|
||||
$action = 'create';
|
||||
} else {
|
||||
$result = $equipmentType->create($user);
|
||||
if ($result > 0) {
|
||||
// Create default fields for common equipment
|
||||
$defaultFields = array(
|
||||
array('code' => 'characteristic', 'label' => 'Charakteristik', 'type' => 'select', 'options' => 'B|C|D|K|Z', 'position' => 10, 'show_in_hover' => 1, 'show_on_block' => 1),
|
||||
array('code' => 'ampere', 'label' => 'Nennstrom (A)', 'type' => 'select', 'options' => '6|10|13|16|20|25|32|40|50|63', 'position' => 20, 'show_in_hover' => 1, 'show_on_block' => 1),
|
||||
array('code' => 'pole', 'label' => 'Polzahl', 'type' => 'select', 'options' => '1|2|3|3+N', 'position' => 30, 'show_in_hover' => 1, 'show_on_block' => 0),
|
||||
array('code' => 'circuit', 'label' => 'Stromkreis', 'type' => 'text', 'options' => '', 'position' => 40, 'show_in_hover' => 1, 'show_on_block' => 0),
|
||||
);
|
||||
|
||||
foreach ($defaultFields as $field) {
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field";
|
||||
$sql .= " (fk_equipment_type, field_code, field_label, field_type, field_options, show_in_hover, show_on_block, required, position, active)";
|
||||
$sql .= " VALUES (".((int) $equipmentType->id).", '".$db->escape($field['code'])."', '".$db->escape($field['label'])."',";
|
||||
$sql .= " '".$db->escape($field['type'])."', '".$db->escape($field['options'])."', ".((int) $field['show_in_hover']).", ".((int) $field['show_on_block']).", 0, ".((int) $field['position']).", 1)";
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
header('Location: '.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$equipmentType->id.'&system='.$equipmentType->fk_system);
|
||||
exit;
|
||||
} else {
|
||||
setEventMessages($equipmentType->error, $equipmentType->errors, 'errors');
|
||||
$action = 'create';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($action == 'update') {
|
||||
$equipmentType->fetch($typeId);
|
||||
$equipmentType->ref = GETPOST('ref', 'aZ09');
|
||||
$equipmentType->label = GETPOST('label', 'alphanohtml');
|
||||
$equipmentType->label_short = GETPOST('label_short', 'alphanohtml');
|
||||
$equipmentType->description = GETPOST('description', 'restricthtml');
|
||||
$equipmentType->fk_system = GETPOSTINT('fk_system');
|
||||
$equipmentType->width_te = GETPOSTINT('width_te');
|
||||
$equipmentType->color = GETPOST('color', 'alphanohtml');
|
||||
$equipmentType->fk_product = GETPOSTINT('fk_product');
|
||||
$equipmentType->terminals_config = GETPOST('terminals_config', 'nohtml');
|
||||
$equipmentType->picto = GETPOST('picto', 'alphanohtml');
|
||||
$equipmentType->position = GETPOSTINT('position');
|
||||
|
||||
$result = $equipmentType->update($user);
|
||||
if ($result > 0) {
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
header('Location: '.$_SERVER['PHP_SELF'].'?system='.$equipmentType->fk_system);
|
||||
exit;
|
||||
} else {
|
||||
setEventMessages($equipmentType->error, $equipmentType->errors, 'errors');
|
||||
$action = 'edit';
|
||||
}
|
||||
}
|
||||
|
||||
if ($action == 'confirm_delete' && $confirm == 'yes') {
|
||||
$equipmentType->fetch($typeId);
|
||||
$result = $equipmentType->delete($user);
|
||||
if ($result > 0) {
|
||||
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($equipmentType->error, $equipmentType->errors, 'errors');
|
||||
}
|
||||
$action = '';
|
||||
}
|
||||
|
||||
if ($action == 'activate') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."kundenkarte_equipment_type SET active = 1 WHERE rowid = ".((int) $typeId);
|
||||
$db->query($sql);
|
||||
$action = '';
|
||||
}
|
||||
|
||||
if ($action == 'deactivate') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."kundenkarte_equipment_type SET active = 0 WHERE rowid = ".((int) $typeId);
|
||||
$db->query($sql);
|
||||
$action = '';
|
||||
}
|
||||
|
||||
// Copy type with all fields
|
||||
if ($action == 'copy' && $typeId > 0) {
|
||||
$sourceType = new EquipmentType($db);
|
||||
if ($sourceType->fetch($typeId) > 0) {
|
||||
$newType = new EquipmentType($db);
|
||||
$newType->ref = $sourceType->ref.'_COPY';
|
||||
$newType->label = $sourceType->label.' (Kopie)';
|
||||
$newType->label_short = $sourceType->label_short;
|
||||
$newType->description = $sourceType->description;
|
||||
$newType->fk_system = $sourceType->fk_system;
|
||||
$newType->width_te = $sourceType->width_te;
|
||||
$newType->color = $sourceType->color;
|
||||
$newType->fk_product = $sourceType->fk_product;
|
||||
$newType->picto = $sourceType->picto;
|
||||
$newType->position = $sourceType->position + 1;
|
||||
$newType->active = 1;
|
||||
|
||||
$result = $newType->create($user);
|
||||
if ($result > 0) {
|
||||
// Copy all fields from source type
|
||||
$sourceFields = $sourceType->fetchFields(0);
|
||||
foreach ($sourceFields as $field) {
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field";
|
||||
$sql .= " (fk_equipment_type, field_code, field_label, field_type, field_options, show_in_hover, show_on_block, required, position, active)";
|
||||
$sql .= " VALUES (".((int) $newType->id).", '".$db->escape($field->field_code)."', '".$db->escape($field->field_label)."',";
|
||||
$sql .= " '".$db->escape($field->field_type)."', '".$db->escape($field->field_options)."', ".((int) $field->show_in_hover).",";
|
||||
$sql .= " ".((int) $field->show_on_block).", ".((int) $field->required).", ".((int) $field->position).", ".((int) $field->active).")";
|
||||
$db->query($sql);
|
||||
}
|
||||
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
header('Location: '.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$newType->id.'&system='.$newType->fk_system);
|
||||
exit;
|
||||
} else {
|
||||
setEventMessages($newType->error, $newType->errors, 'errors');
|
||||
}
|
||||
}
|
||||
$action = '';
|
||||
}
|
||||
|
||||
// Field actions
|
||||
$fieldId = GETPOSTINT('fieldid');
|
||||
|
||||
if ($action == 'add_field') {
|
||||
$fieldCode = GETPOST('field_code', 'aZ09');
|
||||
$fieldLabel = GETPOST('field_label', 'alphanohtml');
|
||||
$fieldType = GETPOST('field_type', 'aZ09');
|
||||
$fieldOptions = GETPOST('field_options', 'nohtml');
|
||||
$showInHover = GETPOSTINT('show_in_hover');
|
||||
$showOnBlock = GETPOSTINT('show_on_block');
|
||||
$isRequired = GETPOSTINT('is_required');
|
||||
$fieldPosition = GETPOSTINT('field_position');
|
||||
|
||||
if (empty($fieldCode) || empty($fieldLabel) || empty($fieldType)) {
|
||||
setEventMessages($langs->trans('ErrorFieldRequired'), null, 'errors');
|
||||
} else {
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field";
|
||||
$sql .= " (fk_equipment_type, field_code, field_label, field_type, field_options, show_in_hover, show_on_block, required, position, active)";
|
||||
$sql .= " VALUES (".((int) $typeId).", '".$db->escape($fieldCode)."', '".$db->escape($fieldLabel)."',";
|
||||
$sql .= " '".$db->escape($fieldType)."', '".$db->escape($fieldOptions)."',";
|
||||
$sql .= " ".((int) $showInHover).", ".((int) $showOnBlock).", ".((int) $isRequired).", ".((int) $fieldPosition).", 1)";
|
||||
|
||||
if ($db->query($sql)) {
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($db->lasterror(), null, 'errors');
|
||||
}
|
||||
}
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
if ($action == 'update_field') {
|
||||
$fieldCode = GETPOST('field_code', 'aZ09');
|
||||
$fieldLabel = GETPOST('field_label', 'alphanohtml');
|
||||
$fieldType = GETPOST('field_type', 'aZ09');
|
||||
$fieldOptions = GETPOST('field_options', 'nohtml');
|
||||
$showInHover = GETPOSTINT('show_in_hover');
|
||||
$showOnBlock = GETPOSTINT('show_on_block');
|
||||
$isRequired = GETPOSTINT('is_required');
|
||||
$fieldPosition = GETPOSTINT('field_position');
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field SET";
|
||||
$sql .= " field_code = '".$db->escape($fieldCode)."',";
|
||||
$sql .= " field_label = '".$db->escape($fieldLabel)."',";
|
||||
$sql .= " field_type = '".$db->escape($fieldType)."',";
|
||||
$sql .= " field_options = '".$db->escape($fieldOptions)."',";
|
||||
$sql .= " show_in_hover = ".((int) $showInHover).",";
|
||||
$sql .= " show_on_block = ".((int) $showOnBlock).",";
|
||||
$sql .= " required = ".((int) $isRequired).",";
|
||||
$sql .= " position = ".((int) $fieldPosition);
|
||||
$sql .= " WHERE rowid = ".((int) $fieldId);
|
||||
|
||||
if ($db->query($sql)) {
|
||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($db->lasterror(), null, 'errors');
|
||||
}
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
if ($action == 'confirm_delete_field' && $confirm == 'yes') {
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field WHERE rowid = ".((int) $fieldId);
|
||||
if ($db->query($sql)) {
|
||||
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($db->lasterror(), null, 'errors');
|
||||
}
|
||||
header('Location: '.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$typeId.'&system='.$systemFilter);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'activate_field') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field SET active = 1 WHERE rowid = ".((int) $fieldId);
|
||||
$db->query($sql);
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
if ($action == 'deactivate_field') {
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field SET active = 0 WHERE rowid = ".((int) $fieldId);
|
||||
$db->query($sql);
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
|
||||
$title = $langs->trans('EquipmentTypes');
|
||||
|
||||
$morejs = array('/kundenkarte/js/kundenkarte.js?v='.time());
|
||||
$morecss = array('/kundenkarte/css/kundenkarte.css?v='.time());
|
||||
|
||||
llxHeader('', $title, '', '', 0, 0, $morejs, $morecss);
|
||||
|
||||
$head = kundenkarteAdminPrepareHead();
|
||||
print dol_get_fiche_head($head, 'equipment_types', $langs->trans('ModuleKundenKarteName'), -1, 'fa-file');
|
||||
|
||||
// Confirmation for type deletion
|
||||
if ($action == 'delete') {
|
||||
print $form->formconfirm(
|
||||
$_SERVER['PHP_SELF'].'?typeid='.$typeId.'&system='.$systemFilter,
|
||||
$langs->trans('Delete'),
|
||||
$langs->trans('ConfirmDeleteType'),
|
||||
'confirm_delete',
|
||||
'',
|
||||
'yes',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
// Confirmation for field deletion
|
||||
if ($action == 'delete_field') {
|
||||
print $form->formconfirm(
|
||||
$_SERVER['PHP_SELF'].'?typeid='.$typeId.'&fieldid='.$fieldId.'&system='.$systemFilter,
|
||||
$langs->trans('Delete'),
|
||||
$langs->trans('ConfirmDeleteField'),
|
||||
'confirm_delete_field',
|
||||
'',
|
||||
'yes',
|
||||
1
|
||||
);
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
// Add/Edit form
|
||||
if (in_array($action, array('create', 'edit'))) {
|
||||
if ($action == 'edit' && $typeId > 0) {
|
||||
$equipmentType->fetch($typeId);
|
||||
}
|
||||
|
||||
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="'.($action == 'edit' ? 'update' : 'add').'">';
|
||||
if ($action == 'edit') {
|
||||
print '<input type="hidden" name="typeid" value="'.$typeId.'">';
|
||||
}
|
||||
|
||||
print '<table class="border centpercent">';
|
||||
|
||||
// System
|
||||
print '<tr><td class="titlefield fieldrequired">'.$langs->trans('System').'</td>';
|
||||
print '<td><select name="fk_system" class="flat minwidth200" required>';
|
||||
print '<option value="">'.$langs->trans('SelectSystem').'</option>';
|
||||
foreach ($systems as $sys) {
|
||||
$sel = ($equipmentType->fk_system == $sys->rowid) ? ' selected' : '';
|
||||
print '<option value="'.$sys->rowid.'"'.$sel.'>'.dol_escape_htmltag($sys->label).'</option>';
|
||||
}
|
||||
print '</select></td></tr>';
|
||||
|
||||
// Reference
|
||||
print '<tr><td class="fieldrequired">'.$langs->trans('TypeRef').'</td>';
|
||||
print '<td><input type="text" name="ref" class="flat minwidth200" value="'.dol_escape_htmltag($equipmentType->ref).'" maxlength="64" required>';
|
||||
print ' <span class="opacitymedium">(UPPERCASE, no spaces)</span></td></tr>';
|
||||
|
||||
// Label
|
||||
print '<tr><td class="fieldrequired">'.$langs->trans('TypeLabel').'</td>';
|
||||
print '<td><input type="text" name="label" class="flat minwidth300" value="'.dol_escape_htmltag($equipmentType->label).'" required></td></tr>';
|
||||
|
||||
// Short label
|
||||
print '<tr><td>'.$langs->trans('TypeShortLabel').'</td>';
|
||||
print '<td><input type="text" name="label_short" class="flat" value="'.dol_escape_htmltag($equipmentType->label_short).'" maxlength="32">';
|
||||
print ' <span class="opacitymedium">(z.B. LS, FI, FI/LS)</span></td></tr>';
|
||||
|
||||
// Description
|
||||
print '<tr><td>'.$langs->trans('Description').'</td>';
|
||||
print '<td><textarea name="description" class="flat minwidth300" rows="2">'.dol_escape_htmltag($equipmentType->description).'</textarea></td></tr>';
|
||||
|
||||
// Width in TE
|
||||
print '<tr><td class="fieldrequired">'.$langs->trans('WidthTE').'</td>';
|
||||
print '<td><input type="number" name="width_te" class="flat" value="'.($equipmentType->width_te ?: 1).'" min="1" max="12" required>';
|
||||
print ' <span class="opacitymedium">'.$langs->trans('WidthTEHelp').'</span></td></tr>';
|
||||
|
||||
// Color
|
||||
print '<tr><td>'.$langs->trans('Color').'</td>';
|
||||
print '<td><input type="color" name="color" value="'.($equipmentType->color ?: '#3498db').'" style="width:60px;height:30px;padding:0;border:1px solid #ccc;">';
|
||||
print ' <span class="opacitymedium">'.$langs->trans('ColorForSVG').'</span></td></tr>';
|
||||
|
||||
// Product
|
||||
print '<tr><td>'.$langs->trans('LinkedProduct').'</td>';
|
||||
print '<td><select name="fk_product" class="flat minwidth300">';
|
||||
print '<option value="0">'.$langs->trans('None').'</option>';
|
||||
foreach ($products as $prod) {
|
||||
$sel = ($equipmentType->fk_product == $prod->rowid) ? ' selected' : '';
|
||||
print '<option value="'.$prod->rowid.'"'.$sel.'>'.dol_escape_htmltag($prod->ref.' - '.$prod->label).'</option>';
|
||||
}
|
||||
print '</select></td></tr>';
|
||||
|
||||
// Icon
|
||||
print '<tr><td>'.$langs->trans('SystemPicto').'</td>';
|
||||
print '<td><div class="kundenkarte-icon-picker-wrapper">';
|
||||
print '<span class="kundenkarte-icon-preview">';
|
||||
if ($equipmentType->picto) {
|
||||
print kundenkarte_render_icon($equipmentType->picto);
|
||||
}
|
||||
print '</span>';
|
||||
print '<input type="text" name="picto" class="flat minwidth200" value="'.dol_escape_htmltag($equipmentType->picto).'" placeholder="fa-bolt">';
|
||||
print '<button type="button" class="kundenkarte-icon-picker-btn" data-input="picto"><i class="fa fa-th"></i> '.$langs->trans('SelectIcon').'</button>';
|
||||
print '</div></td></tr>';
|
||||
|
||||
// Position
|
||||
print '<tr><td>'.$langs->trans('Position').'</td>';
|
||||
print '<td><input type="number" name="position" class="flat" value="'.($equipmentType->position ?: 0).'" min="0"></td></tr>';
|
||||
|
||||
// Terminal configuration
|
||||
print '<tr><td>'.$langs->trans('TerminalConfig').'</td>';
|
||||
print '<td>';
|
||||
print '<div style="margin-bottom:10px;">';
|
||||
print '<label style="margin-right:15px;"><strong>Vorlagen:</strong></label>';
|
||||
print '<button type="button" class="button small" onclick="setTerminals(\'1P\')">1-polig</button> ';
|
||||
print '<button type="button" class="button small" onclick="setTerminals(\'2P\')">2-polig (L+N)</button> ';
|
||||
print '<button type="button" class="button small" onclick="setTerminals(\'3P\')">3-polig</button> ';
|
||||
print '<button type="button" class="button small" onclick="setTerminals(\'4P\')">4-polig (3P+N)</button>';
|
||||
print '</div>';
|
||||
print '<textarea name="terminals_config" id="terminals_config" class="flat" rows="4" style="width:100%;font-family:monospace;font-size:11px;" placeholder=\'{"terminals":[{"id":"t1","label":"L","pos":"top"},{"id":"t2","label":"L","pos":"bottom"}]}\'>';
|
||||
print dol_escape_htmltag($equipmentType->terminals_config);
|
||||
print '</textarea>';
|
||||
print '<div class="opacitymedium small" style="margin-top:5px;">';
|
||||
print 'JSON-Format: <code>{"terminals":[{"id":"t1","label":"L","pos":"top"},...]}</code> - pos: "top" oder "bottom"';
|
||||
print '</div>';
|
||||
print '</td></tr>';
|
||||
|
||||
print '</table>';
|
||||
|
||||
// JavaScript for terminal presets
|
||||
print '<script>
|
||||
function setTerminals(type) {
|
||||
var configs = {
|
||||
"1P": {"terminals":[{"id":"t1","label":"●","pos":"top"},{"id":"t2","label":"●","pos":"bottom"}]},
|
||||
"2P": {"terminals":[{"id":"t1","label":"L","pos":"top"},{"id":"t2","label":"N","pos":"top"},{"id":"t3","label":"L","pos":"bottom"},{"id":"t4","label":"N","pos":"bottom"}]},
|
||||
"3P": {"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"L1","pos":"bottom"},{"id":"t5","label":"L2","pos":"bottom"},{"id":"t6","label":"L3","pos":"bottom"}]},
|
||||
"4P": {"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"N","pos":"top"},{"id":"t5","label":"L1","pos":"bottom"},{"id":"t6","label":"L2","pos":"bottom"},{"id":"t7","label":"L3","pos":"bottom"},{"id":"t8","label":"N","pos":"bottom"}]}
|
||||
};
|
||||
if (configs[type]) {
|
||||
document.getElementById("terminals_config").value = JSON.stringify(configs[type], null, 2);
|
||||
}
|
||||
}
|
||||
</script>';
|
||||
|
||||
print '<div class="center" style="margin-top:20px;">';
|
||||
print '<button type="submit" class="button">'.$langs->trans('Save').'</button>';
|
||||
print ' <a class="button button-cancel" href="'.$_SERVER['PHP_SELF'].'?system='.$systemFilter.'">'.$langs->trans('Cancel').'</a>';
|
||||
print '</div>';
|
||||
|
||||
print '</form>';
|
||||
|
||||
// Fields management for existing type
|
||||
if ($action == 'edit' && $typeId > 0) {
|
||||
$editFieldId = GETPOSTINT('editfield');
|
||||
|
||||
print '<br><br>';
|
||||
print '<h3>'.$langs->trans('EquipmentTypeFields').'</h3>';
|
||||
|
||||
$fields = $equipmentType->fetchFields(0);
|
||||
|
||||
// Field types available
|
||||
$fieldTypes = array(
|
||||
'text' => 'Textfeld (einzeilig)',
|
||||
'textarea' => 'Textfeld (mehrzeilig)',
|
||||
'number' => 'Zahlenfeld',
|
||||
'select' => 'Dropdown-Auswahl',
|
||||
'date' => 'Datumsfeld',
|
||||
'checkbox' => 'Checkbox (Ja/Nein)',
|
||||
);
|
||||
|
||||
// Output edit forms BEFORE the table
|
||||
foreach ($fields as $field) {
|
||||
if ($editFieldId == $field->rowid) {
|
||||
$formId = 'editfield_'.$field->rowid;
|
||||
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="'.$formId.'">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="update_field">';
|
||||
print '<input type="hidden" name="typeid" value="'.$typeId.'">';
|
||||
print '<input type="hidden" name="fieldid" value="'.$field->rowid.'">';
|
||||
print '<input type="hidden" name="system" value="'.$systemFilter.'">';
|
||||
print '</form>';
|
||||
}
|
||||
}
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<th>'.$langs->trans('FieldCode').'</th>';
|
||||
print '<th>'.$langs->trans('FieldLabel').'</th>';
|
||||
print '<th>'.$langs->trans('FieldType').'</th>';
|
||||
print '<th>'.$langs->trans('FieldOptions').'</th>';
|
||||
print '<th class="center">'.$langs->trans('ShowInHover').'</th>';
|
||||
print '<th class="center">'.$langs->trans('ShowOnBlock').'</th>';
|
||||
print '<th class="center">'.$langs->trans('IsRequired').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Position').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Status').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Actions').'</th>';
|
||||
print '</tr>';
|
||||
|
||||
foreach ($fields as $field) {
|
||||
if ($editFieldId == $field->rowid) {
|
||||
$formId = 'editfield_'.$field->rowid;
|
||||
|
||||
print '<tr class="oddeven">';
|
||||
print '<td><input type="text" name="field_code" form="'.$formId.'" class="flat minwidth100" value="'.dol_escape_htmltag($field->field_code).'" required></td>';
|
||||
print '<td><input type="text" name="field_label" form="'.$formId.'" class="flat minwidth150" value="'.dol_escape_htmltag($field->field_label).'" required></td>';
|
||||
print '<td><select name="field_type" form="'.$formId.'" class="flat">';
|
||||
foreach ($fieldTypes as $ftype => $flabel) {
|
||||
$sel = ($field->field_type == $ftype) ? ' selected' : '';
|
||||
print '<option value="'.$ftype.'"'.$sel.'>'.$flabel.'</option>';
|
||||
}
|
||||
print '</select></td>';
|
||||
print '<td><input type="text" name="field_options" form="'.$formId.'" class="flat minwidth100" value="'.dol_escape_htmltag($field->field_options).'" placeholder="opt1|opt2|opt3"></td>';
|
||||
print '<td class="center"><input type="checkbox" name="show_in_hover" form="'.$formId.'" value="1"'.($field->show_in_hover ? ' checked' : '').'></td>';
|
||||
print '<td class="center"><input type="checkbox" name="show_on_block" form="'.$formId.'" value="1"'.($field->show_on_block ? ' checked' : '').'></td>';
|
||||
print '<td class="center"><input type="checkbox" name="is_required" form="'.$formId.'" value="1"'.($field->required ? ' checked' : '').'></td>';
|
||||
print '<td class="center"><input type="number" name="field_position" form="'.$formId.'" class="flat" style="width:50px;" value="'.$field->position.'" min="0"></td>';
|
||||
print '<td></td>';
|
||||
print '<td class="center nowraponall">';
|
||||
print '<div style="display:inline-flex;gap:8px;">';
|
||||
print '<button type="submit" form="'.$formId.'" class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;background:#28a745;border-color:#28a745;color:#fff;" title="'.$langs->trans('Save').'"><i class="fas fa-save"></i></button>';
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;" href="'.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$typeId.'&system='.$systemFilter.'" title="'.$langs->trans('Cancel').'"><i class="fas fa-times"></i></a>';
|
||||
print '</div>';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
} else {
|
||||
print '<tr class="oddeven">';
|
||||
print '<td>'.dol_escape_htmltag($field->field_code).'</td>';
|
||||
print '<td>'.dol_escape_htmltag($field->field_label).'</td>';
|
||||
print '<td>'.dol_escape_htmltag($fieldTypes[$field->field_type] ?? $field->field_type).'</td>';
|
||||
print '<td class="small opacitymedium">'.dol_escape_htmltag(dol_trunc($field->field_options, 20)).'</td>';
|
||||
print '<td class="center">'.($field->show_in_hover ? img_picto('', 'tick') : '').'</td>';
|
||||
print '<td class="center">'.($field->show_on_block ? img_picto('', 'tick') : '').'</td>';
|
||||
print '<td class="center">'.($field->required ? img_picto('', 'tick') : '').'</td>';
|
||||
print '<td class="center">'.$field->position.'</td>';
|
||||
print '<td class="center">';
|
||||
if ($field->active) {
|
||||
print '<a href="'.$_SERVER['PHP_SELF'].'?action=deactivate_field&typeid='.$typeId.'&fieldid='.$field->rowid.'&system='.$systemFilter.'&token='.newToken().'">'.img_picto($langs->trans('Enabled'), 'switch_on').'</a>';
|
||||
} else {
|
||||
print '<a href="'.$_SERVER['PHP_SELF'].'?action=activate_field&typeid='.$typeId.'&fieldid='.$field->rowid.'&system='.$systemFilter.'&token='.newToken().'">'.img_picto($langs->trans('Disabled'), 'switch_off').'</a>';
|
||||
}
|
||||
print '</td>';
|
||||
print '<td class="center nowraponall">';
|
||||
print '<div style="display:inline-flex;gap:8px;">';
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;" href="'.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$typeId.'&editfield='.$field->rowid.'&system='.$systemFilter.'" title="'.$langs->trans('Edit').'"><i class="fas fa-pen"></i></a>';
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;background:#dc3545;border-color:#dc3545;color:#fff;" href="'.$_SERVER['PHP_SELF'].'?action=delete_field&typeid='.$typeId.'&fieldid='.$field->rowid.'&system='.$systemFilter.'&token='.newToken().'" title="'.$langs->trans('Delete').'"><i class="fas fa-trash"></i></a>';
|
||||
print '</div>';
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($fields)) {
|
||||
print '<tr class="oddeven"><td colspan="10" class="opacitymedium">'.$langs->trans('NoFieldsDefined').'</td></tr>';
|
||||
}
|
||||
|
||||
print '</table>';
|
||||
|
||||
// Add new field form
|
||||
print '<div class="margintoponlyshort">';
|
||||
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="add_field">';
|
||||
print '<input type="hidden" name="typeid" value="'.$typeId.'">';
|
||||
print '<input type="hidden" name="system" value="'.$systemFilter.'">';
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<th colspan="10">'.$langs->trans('Add').' '.$langs->trans('Field').'</th>';
|
||||
print '</tr>';
|
||||
print '<tr class="oddeven">';
|
||||
print '<td><input type="text" name="field_code" class="flat minwidth100" placeholder="CODE" required></td>';
|
||||
print '<td><input type="text" name="field_label" class="flat minwidth150" placeholder="'.$langs->trans('FieldLabel').'" required></td>';
|
||||
print '<td><select name="field_type" class="flat" required>';
|
||||
print '<option value="">'.$langs->trans('Select').'</option>';
|
||||
foreach ($fieldTypes as $ftype => $flabel) {
|
||||
print '<option value="'.$ftype.'">'.$flabel.'</option>';
|
||||
}
|
||||
print '</select></td>';
|
||||
print '<td><input type="text" name="field_options" class="flat minwidth100" placeholder="opt1|opt2"></td>';
|
||||
print '<td class="center"><input type="checkbox" name="show_in_hover" value="1" checked></td>';
|
||||
print '<td class="center"><input type="checkbox" name="show_on_block" value="1"></td>';
|
||||
print '<td class="center"><input type="checkbox" name="is_required" value="1"></td>';
|
||||
print '<td class="center"><input type="number" name="field_position" class="flat" style="width:50px;" value="0" min="0"></td>';
|
||||
print '<td></td>';
|
||||
print '<td class="center"><button type="submit" class="button buttongen"><i class="fa fa-plus"></i> '.$langs->trans('Add').'</button></td>';
|
||||
print '</tr>';
|
||||
print '</table>';
|
||||
print '</form>';
|
||||
print '</div>';
|
||||
|
||||
// Help box
|
||||
print '<div class="info" style="margin-top:15px;">';
|
||||
print '<p><strong><i class="fa fa-info-circle"></i> Hilfe: Equipment-Felder</strong></p>';
|
||||
print '<table class="noborder" style="margin-top:10px;">';
|
||||
print '<tr><td style="width:200px;"><strong>Show in Hover</strong></td><td>Feld wird im Tooltip angezeigt</td></tr>';
|
||||
print '<tr><td><strong>Show on Block</strong></td><td>Feld wird direkt auf dem SVG-Block angezeigt (z.B. "B16")</td></tr>';
|
||||
print '<tr><td><strong>Dropdown-Auswahl</strong></td><td>Optionen mit <code>|</code> trennen, z.B.: <code>B|C|D</code> oder <code>6|10|16|20|25|32</code></td></tr>';
|
||||
print '</table>';
|
||||
print '</div>';
|
||||
}
|
||||
|
||||
} else {
|
||||
// System filter
|
||||
print '<form method="GET" action="'.$_SERVER['PHP_SELF'].'" style="margin-bottom:15px;">';
|
||||
print $langs->trans('FilterBySystem').': ';
|
||||
print '<select name="system" class="flat" onchange="this.form.submit();">';
|
||||
print '<option value="0">'.$langs->trans('All').'</option>';
|
||||
foreach ($systems as $sys) {
|
||||
$sel = ($systemFilter == $sys->rowid) ? ' selected' : '';
|
||||
print '<option value="'.$sys->rowid.'"'.$sel.'>'.dol_escape_htmltag($sys->label).'</option>';
|
||||
}
|
||||
print '</select>';
|
||||
print '</form>';
|
||||
|
||||
// Add button
|
||||
print '<div style="margin-bottom:15px;">';
|
||||
print '<a class="button" href="'.$_SERVER['PHP_SELF'].'?action=create&system='.$systemFilter.'">';
|
||||
print '<i class="fa fa-plus"></i> '.$langs->trans('AddEquipmentType');
|
||||
print '</a>';
|
||||
print '</div>';
|
||||
|
||||
// List
|
||||
$types = $equipmentType->fetchAllBySystem($systemFilter, 0);
|
||||
|
||||
print '<table class="noborder centpercent">';
|
||||
print '<tr class="liste_titre">';
|
||||
print '<th>'.$langs->trans('TypeRef').'</th>';
|
||||
print '<th>'.$langs->trans('TypeLabel').'</th>';
|
||||
print '<th>'.$langs->trans('System').'</th>';
|
||||
print '<th class="center">'.$langs->trans('WidthTE').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Color').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Position').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Status').'</th>';
|
||||
print '<th class="center">'.$langs->trans('Actions').'</th>';
|
||||
print '</tr>';
|
||||
|
||||
foreach ($types as $type) {
|
||||
print '<tr class="oddeven">';
|
||||
|
||||
print '<td>';
|
||||
if ($type->picto) {
|
||||
print kundenkarte_render_icon($type->picto).' ';
|
||||
}
|
||||
print dol_escape_htmltag($type->ref).'</td>';
|
||||
|
||||
print '<td>'.dol_escape_htmltag($type->label);
|
||||
if ($type->label_short) {
|
||||
print ' <span class="opacitymedium">('.$type->label_short.')</span>';
|
||||
}
|
||||
print '</td>';
|
||||
|
||||
print '<td>'.dol_escape_htmltag($type->system_label).'</td>';
|
||||
print '<td class="center">'.$type->width_te.' TE</td>';
|
||||
print '<td class="center"><span style="display:inline-block;width:24px;height:24px;background:'.($type->color ?: '#3498db').';border-radius:3px;"></span></td>';
|
||||
print '<td class="center">'.$type->position.'</td>';
|
||||
|
||||
print '<td class="center">';
|
||||
if ($type->active) {
|
||||
print '<a href="'.$_SERVER['PHP_SELF'].'?action=deactivate&typeid='.$type->id.'&system='.$systemFilter.'&token='.newToken().'">'.img_picto($langs->trans('Enabled'), 'switch_on').'</a>';
|
||||
} else {
|
||||
print '<a href="'.$_SERVER['PHP_SELF'].'?action=activate&typeid='.$type->id.'&system='.$systemFilter.'&token='.newToken().'">'.img_picto($langs->trans('Disabled'), 'switch_off').'</a>';
|
||||
}
|
||||
print '</td>';
|
||||
|
||||
print '<td class="center nowraponall">';
|
||||
print '<div style="display:inline-flex;gap:8px;">';
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;" href="'.$_SERVER['PHP_SELF'].'?action=edit&typeid='.$type->id.'&system='.$systemFilter.'" title="'.$langs->trans('Edit').'"><i class="fas fa-pen"></i></a>';
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;" href="'.$_SERVER['PHP_SELF'].'?action=copy&typeid='.$type->id.'&system='.$systemFilter.'&token='.newToken().'" title="'.$langs->trans('Copy').'"><i class="fas fa-copy"></i></a>';
|
||||
if (!$type->is_system) {
|
||||
print '<a class="button buttongen" style="width:32px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center;background:#dc3545;border-color:#dc3545;color:#fff;" href="'.$_SERVER['PHP_SELF'].'?action=delete&typeid='.$type->id.'&system='.$systemFilter.'" title="'.$langs->trans('Delete').'" onclick="return confirm(\''.$langs->trans('ConfirmDelete').'\');"><i class="fas fa-trash"></i></a>';
|
||||
}
|
||||
print '</div>';
|
||||
print '</td>';
|
||||
|
||||
print '</tr>';
|
||||
}
|
||||
|
||||
if (empty($types)) {
|
||||
print '<tr class="oddeven"><td colspan="8" class="opacitymedium">'.$langs->trans('NoRecords').'</td></tr>';
|
||||
}
|
||||
|
||||
print '</table>';
|
||||
}
|
||||
|
||||
print dol_get_fiche_end();
|
||||
|
||||
llxFooter();
|
||||
$db->close();
|
||||
355
ajax/equipment.php
Normal file
355
ajax/equipment.php
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* AJAX endpoint for equipment (Sicherungsautomaten, etc.)
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1');
|
||||
if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
|
||||
if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
|
||||
if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
|
||||
|
||||
$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.'/custom/kundenkarte/class/equipment.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmenttype.class.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$equipmentId = GETPOSTINT('equipment_id');
|
||||
$carrierId = GETPOSTINT('carrier_id');
|
||||
|
||||
$equipment = new Equipment($db);
|
||||
|
||||
$response = array('success' => false, 'error' => '');
|
||||
|
||||
// Security check
|
||||
if (!$user->hasRight('kundenkarte', 'read')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'get_types':
|
||||
// Get all equipment types for dropdown
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmenttype.class.php';
|
||||
$eqType = new EquipmentType($db);
|
||||
$systemId = GETPOSTINT('system_id');
|
||||
$types = $eqType->fetchAllBySystem($systemId, 1); // Filter by system if provided, only active
|
||||
|
||||
$result = array();
|
||||
foreach ($types as $t) {
|
||||
$result[] = array(
|
||||
'id' => $t->id,
|
||||
'label' => $t->label,
|
||||
'label_short' => $t->label_short,
|
||||
'width_te' => $t->width_te,
|
||||
'color' => $t->color
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['types'] = $result;
|
||||
break;
|
||||
|
||||
case 'get':
|
||||
// Get single equipment data
|
||||
if ($equipmentId > 0 && $equipment->fetch($equipmentId) > 0) {
|
||||
$response['success'] = true;
|
||||
$response['equipment'] = array(
|
||||
'id' => $equipment->id,
|
||||
'fk_carrier' => $equipment->fk_carrier,
|
||||
'type_id' => $equipment->fk_equipment_type,
|
||||
'type_label' => $equipment->type_label,
|
||||
'label' => $equipment->label,
|
||||
'position_te' => $equipment->position_te,
|
||||
'width_te' => $equipment->width_te,
|
||||
'field_values' => $equipment->getFieldValues(),
|
||||
'fk_product' => $equipment->fk_product,
|
||||
'fk_protection' => $equipment->fk_protection,
|
||||
'protection_label' => $equipment->protection_label
|
||||
);
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'get_protection_devices':
|
||||
// Get all protection devices (FI/RCD) for an Anlage
|
||||
$anlageId = GETPOSTINT('anlage_id');
|
||||
if ($anlageId > 0) {
|
||||
$devices = $equipment->fetchProtectionDevices($anlageId);
|
||||
$result = array();
|
||||
foreach ($devices as $d) {
|
||||
$result[] = array(
|
||||
'id' => $d->id,
|
||||
'label' => $d->label ?: $d->type_label,
|
||||
'type_label' => $d->type_label,
|
||||
'type_label_short' => $d->type_label_short,
|
||||
'display_label' => ($d->label ?: $d->type_label_short ?: $d->type_label).' (Pos. '.$d->position_te.')'
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['devices'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
// List all equipment on a carrier
|
||||
if ($carrierId > 0) {
|
||||
$items = $equipment->fetchByCarrier($carrierId);
|
||||
$result = array();
|
||||
foreach ($items as $eq) {
|
||||
$result[] = array(
|
||||
'id' => $eq->id,
|
||||
'type_id' => $eq->fk_equipment_type,
|
||||
'type_label' => $eq->type_label,
|
||||
'type_label_short' => $eq->type_label_short,
|
||||
'type_ref' => $eq->type_ref,
|
||||
'type_color' => $eq->type_color,
|
||||
'terminals_config' => $eq->terminals_config,
|
||||
'label' => $eq->label,
|
||||
'position_te' => $eq->position_te,
|
||||
'width_te' => $eq->width_te,
|
||||
'block_label' => $eq->getBlockLabel(),
|
||||
'block_color' => $eq->getBlockColor(),
|
||||
'field_values' => $eq->getFieldValues(),
|
||||
'fk_product' => $eq->fk_product
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['equipment'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing carrier_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$equipment->fk_carrier = $carrierId;
|
||||
$equipment->fk_equipment_type = GETPOSTINT('type_id');
|
||||
$equipment->label = GETPOST('label', 'alphanohtml');
|
||||
$equipment->position_te = GETPOSTINT('position_te');
|
||||
$equipment->width_te = GETPOSTINT('width_te');
|
||||
$equipment->fk_product = GETPOSTINT('fk_product');
|
||||
$equipment->fk_protection = GETPOSTINT('fk_protection');
|
||||
$equipment->protection_label = GETPOST('protection_label', 'alphanohtml');
|
||||
|
||||
// Field values
|
||||
$fieldValues = GETPOST('field_values', 'nohtml');
|
||||
if ($fieldValues) {
|
||||
$equipment->field_values = $fieldValues;
|
||||
}
|
||||
|
||||
// If no width specified, get from type
|
||||
if (empty($equipment->width_te)) {
|
||||
$type = new EquipmentType($db);
|
||||
if ($type->fetch($equipment->fk_equipment_type) > 0) {
|
||||
$equipment->width_te = $type->width_te;
|
||||
} else {
|
||||
$equipment->width_te = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check carrier and position
|
||||
$carrier = new EquipmentCarrier($db);
|
||||
if ($carrier->fetch($carrierId) > 0) {
|
||||
// If no position specified, find next free position (1-based)
|
||||
if (empty($equipment->position_te)) {
|
||||
$equipment->position_te = $carrier->getNextFreePosition($equipment->width_te);
|
||||
if ($equipment->position_te < 0) {
|
||||
$response['error'] = 'No free position available on carrier';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if position is available
|
||||
if (!$carrier->isPositionAvailable($equipment->position_te, $equipment->width_te)) {
|
||||
$response['error'] = 'Position not available';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $equipment->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['equipment_id'] = $result;
|
||||
$response['block_label'] = $equipment->getBlockLabel();
|
||||
} else {
|
||||
$response['error'] = $equipment->error;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$newPosition = GETPOSTINT('position_te');
|
||||
$newWidth = GETPOSTINT('width_te') ?: $equipment->width_te;
|
||||
|
||||
// Check if new position is available (excluding current equipment)
|
||||
if ($newPosition != $equipment->position_te || $newWidth != $equipment->width_te) {
|
||||
$carrier = new EquipmentCarrier($db);
|
||||
if ($carrier->fetch($equipment->fk_carrier) > 0) {
|
||||
if (!$carrier->isPositionAvailable($newPosition, $newWidth, $equipmentId)) {
|
||||
$response['error'] = 'Position not available';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$equipment->fk_equipment_type = GETPOSTINT('type_id') ?: $equipment->fk_equipment_type;
|
||||
$equipment->label = GETPOST('label', 'alphanohtml');
|
||||
$equipment->position_te = $newPosition;
|
||||
$equipment->width_te = $newWidth;
|
||||
$equipment->fk_product = GETPOSTINT('fk_product');
|
||||
$equipment->fk_protection = GETPOSTINT('fk_protection');
|
||||
$equipment->protection_label = GETPOST('protection_label', 'alphanohtml');
|
||||
|
||||
$fieldValues = GETPOST('field_values', 'nohtml');
|
||||
if ($fieldValues) {
|
||||
$equipment->field_values = $fieldValues;
|
||||
}
|
||||
|
||||
$result = $equipment->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['block_label'] = $equipment->getBlockLabel();
|
||||
} else {
|
||||
$response['error'] = $equipment->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update_position':
|
||||
// Quick position update for drag-drop
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$newPosition = GETPOSTINT('position_te');
|
||||
|
||||
// Check if new position is available
|
||||
if ($newPosition != $equipment->position_te) {
|
||||
$carrier = new EquipmentCarrier($db);
|
||||
if ($carrier->fetch($equipment->fk_carrier) > 0) {
|
||||
if (!$carrier->isPositionAvailable($newPosition, $equipment->width_te, $equipmentId)) {
|
||||
$response['error'] = 'Position not available';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$equipment->position_te = $newPosition;
|
||||
$result = $equipment->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $equipment->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!$user->hasRight('kundenkarte', 'delete')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$result = $equipment->delete($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $equipment->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$newId = $equipment->duplicate($user);
|
||||
if ($newId > 0) {
|
||||
$response['success'] = true;
|
||||
$response['equipment_id'] = $newId;
|
||||
|
||||
// Fetch the new equipment to return its data
|
||||
$newEquipment = new Equipment($db);
|
||||
if ($newEquipment->fetch($newId) > 0) {
|
||||
$response['equipment'] = array(
|
||||
'id' => $newEquipment->id,
|
||||
'type_id' => $newEquipment->fk_equipment_type,
|
||||
'type_label' => $newEquipment->type_label,
|
||||
'type_color' => $newEquipment->type_color,
|
||||
'label' => $newEquipment->label,
|
||||
'position_te' => $newEquipment->position_te,
|
||||
'width_te' => $newEquipment->width_te,
|
||||
'block_label' => $newEquipment->getBlockLabel(),
|
||||
'block_color' => $newEquipment->getBlockColor()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$response['error'] = $equipment->error ?: 'Duplication failed';
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'move':
|
||||
// Move equipment to new position (for drag & drop)
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$newPosition = GETPOSTINT('position_te');
|
||||
|
||||
$carrier = new EquipmentCarrier($db);
|
||||
if ($carrier->fetch($equipment->fk_carrier) > 0) {
|
||||
if ($carrier->isPositionAvailable($newPosition, $equipment->width_te, $equipmentId)) {
|
||||
$equipment->position_te = $newPosition;
|
||||
$result = $equipment->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $equipment->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Position not available';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Equipment not found';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$response['error'] = 'Unknown action';
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
$db->close();
|
||||
188
ajax/equipment_carrier.php
Normal file
188
ajax/equipment_carrier.php
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* AJAX endpoint for equipment carriers (Hutschienen)
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1');
|
||||
if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
|
||||
if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
|
||||
if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
|
||||
|
||||
$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.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipment.class.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$anlageId = GETPOSTINT('anlage_id');
|
||||
$carrierId = GETPOSTINT('carrier_id');
|
||||
$panelId = GETPOSTINT('panel_id');
|
||||
|
||||
$carrier = new EquipmentCarrier($db);
|
||||
|
||||
$response = array('success' => false, 'error' => '');
|
||||
|
||||
// Security check
|
||||
if (!$user->hasRight('kundenkarte', 'read')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'get':
|
||||
// Get single carrier data
|
||||
if ($carrierId > 0 && $carrier->fetch($carrierId) > 0) {
|
||||
$response['success'] = true;
|
||||
$response['carrier'] = array(
|
||||
'id' => $carrier->id,
|
||||
'fk_anlage' => $carrier->fk_anlage,
|
||||
'fk_panel' => $carrier->fk_panel,
|
||||
'label' => $carrier->label,
|
||||
'total_te' => $carrier->total_te,
|
||||
'position' => $carrier->position,
|
||||
'panel_label' => $carrier->panel_label
|
||||
);
|
||||
} else {
|
||||
$response['error'] = 'Carrier not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
// List all carriers for an Anlage
|
||||
if ($anlageId > 0) {
|
||||
$carriers = $carrier->fetchByAnlage($anlageId);
|
||||
$result = array();
|
||||
foreach ($carriers as $c) {
|
||||
$c->fetchEquipment();
|
||||
$equipment = array();
|
||||
foreach ($c->equipment as $eq) {
|
||||
$equipment[] = array(
|
||||
'id' => $eq->id,
|
||||
'type_id' => $eq->fk_equipment_type,
|
||||
'type_label' => $eq->type_label,
|
||||
'type_label_short' => $eq->type_label_short,
|
||||
'type_color' => $eq->type_color,
|
||||
'label' => $eq->label,
|
||||
'position_te' => $eq->position_te,
|
||||
'width_te' => $eq->width_te,
|
||||
'block_label' => $eq->getBlockLabel(),
|
||||
'block_color' => $eq->getBlockColor(),
|
||||
'field_values' => $eq->getFieldValues()
|
||||
);
|
||||
}
|
||||
$result[] = array(
|
||||
'id' => $c->id,
|
||||
'label' => $c->label,
|
||||
'total_te' => $c->total_te,
|
||||
'used_te' => $c->getUsedTE(),
|
||||
'free_te' => $c->getFreeTE(),
|
||||
'position' => $c->position,
|
||||
'equipment' => $equipment
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['carriers'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
$carrier->fk_anlage = $anlageId;
|
||||
$carrier->fk_panel = $panelId > 0 ? $panelId : null;
|
||||
$carrier->label = GETPOST('label', 'alphanohtml');
|
||||
$carrier->total_te = GETPOSTINT('total_te') ?: 12;
|
||||
|
||||
$result = $carrier->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['carrier_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $carrier->error;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($carrier->fetch($carrierId) > 0) {
|
||||
$carrier->label = GETPOST('label', 'alphanohtml');
|
||||
$carrier->total_te = GETPOSTINT('total_te') ?: $carrier->total_te;
|
||||
$carrier->position = GETPOSTINT('position');
|
||||
// Allow changing panel (0 or empty = no panel)
|
||||
$newPanelId = GETPOSTINT('panel_id');
|
||||
$carrier->fk_panel = $newPanelId > 0 ? $newPanelId : null;
|
||||
|
||||
$result = $carrier->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $carrier->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Carrier not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!$user->hasRight('kundenkarte', 'delete')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($carrier->fetch($carrierId) > 0) {
|
||||
$result = $carrier->delete($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $carrier->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Carrier not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($carrier->fetch($carrierId) > 0) {
|
||||
// Create a copy of the carrier
|
||||
$newCarrier = new EquipmentCarrier($db);
|
||||
$newCarrier->fk_anlage = $carrier->fk_anlage;
|
||||
$newCarrier->fk_panel = $carrier->fk_panel;
|
||||
$newCarrier->label = $carrier->label;
|
||||
$newCarrier->total_te = $carrier->total_te;
|
||||
$newCarrier->note_private = $carrier->note_private;
|
||||
|
||||
$result = $newCarrier->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['carrier_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $newCarrier->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Carrier not found';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$response['error'] = 'Unknown action';
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
$db->close();
|
||||
348
ajax/equipment_connection.php
Normal file
348
ajax/equipment_connection.php
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* AJAX endpoint for equipment connections (generic for all system types)
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1');
|
||||
if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
|
||||
if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
|
||||
if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
|
||||
|
||||
$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.'/custom/kundenkarte/class/equipmentconnection.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipment.class.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$connectionId = GETPOSTINT('connection_id');
|
||||
$carrierId = GETPOSTINT('carrier_id');
|
||||
$equipmentId = GETPOSTINT('equipment_id');
|
||||
|
||||
$connection = new EquipmentConnection($db);
|
||||
|
||||
$response = array('success' => false, 'error' => '');
|
||||
|
||||
// Security check
|
||||
if (!$user->hasRight('kundenkarte', 'read')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'get':
|
||||
// Get single connection data
|
||||
if ($connectionId > 0 && $connection->fetch($connectionId) > 0) {
|
||||
$response['success'] = true;
|
||||
$response['connection'] = array(
|
||||
'id' => $connection->id,
|
||||
'fk_source' => $connection->fk_source,
|
||||
'source_terminal' => $connection->source_terminal,
|
||||
'fk_target' => $connection->fk_target,
|
||||
'target_terminal' => $connection->target_terminal,
|
||||
'connection_type' => $connection->connection_type,
|
||||
'color' => $connection->color,
|
||||
'output_label' => $connection->output_label,
|
||||
'medium_type' => $connection->medium_type,
|
||||
'medium_spec' => $connection->medium_spec,
|
||||
'medium_length' => $connection->medium_length,
|
||||
'is_rail' => $connection->is_rail,
|
||||
'rail_start_te' => $connection->rail_start_te,
|
||||
'rail_end_te' => $connection->rail_end_te,
|
||||
'rail_phases' => $connection->rail_phases,
|
||||
'excluded_te' => $connection->excluded_te,
|
||||
'fk_carrier' => $connection->fk_carrier,
|
||||
'position_y' => $connection->position_y,
|
||||
'source_label' => $connection->source_label,
|
||||
'target_label' => $connection->target_label
|
||||
);
|
||||
} else {
|
||||
$response['error'] = 'Connection not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
// List all connections for a carrier
|
||||
if ($carrierId > 0) {
|
||||
$connections = $connection->fetchByCarrier($carrierId);
|
||||
$result = array();
|
||||
foreach ($connections as $c) {
|
||||
$result[] = array(
|
||||
'id' => $c->id,
|
||||
'fk_source' => $c->fk_source,
|
||||
'source_terminal' => $c->source_terminal,
|
||||
'source_label' => $c->source_label,
|
||||
'source_pos' => $c->source_pos,
|
||||
'source_width' => $c->source_width,
|
||||
'fk_target' => $c->fk_target,
|
||||
'target_terminal' => $c->target_terminal,
|
||||
'target_label' => $c->target_label,
|
||||
'target_pos' => $c->target_pos,
|
||||
'connection_type' => $c->connection_type,
|
||||
'color' => $c->getColor(),
|
||||
'output_label' => $c->output_label,
|
||||
'medium_type' => $c->medium_type,
|
||||
'medium_spec' => $c->medium_spec,
|
||||
'medium_length' => $c->medium_length,
|
||||
'is_rail' => $c->is_rail,
|
||||
'rail_start_te' => $c->rail_start_te,
|
||||
'rail_end_te' => $c->rail_end_te,
|
||||
'rail_phases' => $c->rail_phases,
|
||||
'excluded_te' => $c->excluded_te,
|
||||
'position_y' => $c->position_y,
|
||||
'display_label' => $c->getDisplayLabel()
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['connections'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing carrier_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list_outputs':
|
||||
// List outputs for an equipment
|
||||
if ($equipmentId > 0) {
|
||||
$outputs = $connection->fetchOutputs($equipmentId);
|
||||
$result = array();
|
||||
foreach ($outputs as $c) {
|
||||
$result[] = array(
|
||||
'id' => $c->id,
|
||||
'connection_type' => $c->connection_type,
|
||||
'color' => $c->getColor(),
|
||||
'output_label' => $c->output_label,
|
||||
'medium_type' => $c->medium_type,
|
||||
'medium_spec' => $c->medium_spec,
|
||||
'medium_length' => $c->medium_length,
|
||||
'display_label' => $c->getDisplayLabel()
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['outputs'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing equipment_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$connection->fk_source = GETPOSTINT('fk_source');
|
||||
$connection->source_terminal = GETPOST('source_terminal', 'alphanohtml') ?: 'output';
|
||||
$connection->source_terminal_id = GETPOST('source_terminal_id', 'alphanohtml');
|
||||
$connection->fk_target = GETPOSTINT('fk_target');
|
||||
$connection->target_terminal = GETPOST('target_terminal', 'alphanohtml') ?: 'input';
|
||||
$connection->target_terminal_id = GETPOST('target_terminal_id', 'alphanohtml');
|
||||
$connection->connection_type = GETPOST('connection_type', 'alphanohtml');
|
||||
$connection->color = GETPOST('color', 'alphanohtml');
|
||||
$connection->output_label = GETPOST('output_label', 'alphanohtml');
|
||||
$connection->medium_type = GETPOST('medium_type', 'alphanohtml');
|
||||
$connection->medium_spec = GETPOST('medium_spec', 'alphanohtml');
|
||||
$connection->medium_length = GETPOST('medium_length', 'alphanohtml');
|
||||
$connection->is_rail = GETPOSTINT('is_rail');
|
||||
$connection->rail_start_te = GETPOSTINT('rail_start_te');
|
||||
$connection->rail_end_te = GETPOSTINT('rail_end_te');
|
||||
$connection->fk_carrier = $carrierId;
|
||||
$connection->position_y = GETPOSTINT('position_y');
|
||||
|
||||
$result = $connection->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['connection_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $connection->error ?: 'Create failed';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($connection->fetch($connectionId) > 0) {
|
||||
$connection->fk_source = GETPOSTINT('fk_source');
|
||||
$connection->source_terminal = GETPOST('source_terminal', 'alphanohtml') ?: 'output';
|
||||
$connection->fk_target = GETPOSTINT('fk_target');
|
||||
$connection->target_terminal = GETPOST('target_terminal', 'alphanohtml') ?: 'input';
|
||||
$connection->connection_type = GETPOST('connection_type', 'alphanohtml');
|
||||
$connection->color = GETPOST('color', 'alphanohtml');
|
||||
$connection->output_label = GETPOST('output_label', 'alphanohtml');
|
||||
$connection->medium_type = GETPOST('medium_type', 'alphanohtml');
|
||||
$connection->medium_spec = GETPOST('medium_spec', 'alphanohtml');
|
||||
$connection->medium_length = GETPOST('medium_length', 'alphanohtml');
|
||||
$connection->is_rail = GETPOSTINT('is_rail');
|
||||
$connection->rail_start_te = GETPOSTINT('rail_start_te');
|
||||
$connection->rail_end_te = GETPOSTINT('rail_end_te');
|
||||
$connection->rail_phases = GETPOST('rail_phases', 'alphanohtml');
|
||||
$connection->excluded_te = GETPOST('excluded_te', 'alphanohtml');
|
||||
$connection->position_y = GETPOSTINT('position_y');
|
||||
|
||||
$result = $connection->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $connection->error ?: 'Update failed';
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Connection not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!$user->hasRight('kundenkarte', 'delete')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($connection->fetch($connectionId) > 0) {
|
||||
$result = $connection->delete($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $connection->error ?: 'Delete failed';
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Connection not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create_rail':
|
||||
// Create a rail/bar connection spanning multiple equipment
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$connection->is_rail = 1;
|
||||
$connection->connection_type = GETPOST('connection_type', 'alphanohtml');
|
||||
$connection->color = GETPOST('color', 'alphanohtml');
|
||||
$connection->rail_start_te = GETPOSTINT('rail_start_te');
|
||||
$connection->rail_end_te = GETPOSTINT('rail_end_te');
|
||||
$connection->rail_phases = GETPOST('rail_phases', 'alphanohtml');
|
||||
$connection->excluded_te = GETPOST('excluded_te', 'alphanohtml');
|
||||
$connection->fk_carrier = $carrierId;
|
||||
$connection->position_y = GETPOSTINT('position_y');
|
||||
|
||||
$result = $connection->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['connection_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $connection->error ?: 'Create failed';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create_output':
|
||||
// Create an output connection
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$connection->fk_source = $equipmentId;
|
||||
$connection->source_terminal = 'output';
|
||||
$connection->fk_target = null;
|
||||
$connection->connection_type = GETPOST('connection_type', 'alphanohtml');
|
||||
$connection->color = GETPOST('color', 'alphanohtml');
|
||||
$connection->output_label = GETPOST('output_label', 'alphanohtml');
|
||||
$connection->medium_type = GETPOST('medium_type', 'alphanohtml');
|
||||
$connection->medium_spec = GETPOST('medium_spec', 'alphanohtml');
|
||||
$connection->medium_length = GETPOST('medium_length', 'alphanohtml');
|
||||
$connection->fk_carrier = $carrierId;
|
||||
$connection->position_y = 0;
|
||||
|
||||
$result = $connection->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['connection_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $connection->error ?: 'Create failed';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list_all':
|
||||
// List all connections for an anlage (across all carriers)
|
||||
$anlageId = GETPOSTINT('anlage_id');
|
||||
if ($anlageId > 0) {
|
||||
// Get all carriers for this anlage
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
$carrierObj = new EquipmentCarrier($db);
|
||||
$carriers = $carrierObj->fetchByAnlage($anlageId);
|
||||
|
||||
$allConnections = array();
|
||||
foreach ($carriers as $carrier) {
|
||||
$connections = $connection->fetchByCarrier($carrier->id);
|
||||
foreach ($connections as $c) {
|
||||
$allConnections[] = array(
|
||||
'id' => $c->id,
|
||||
'fk_source' => $c->fk_source,
|
||||
'source_terminal' => $c->source_terminal,
|
||||
'source_terminal_id' => $c->source_terminal_id,
|
||||
'source_label' => $c->source_label,
|
||||
'fk_target' => $c->fk_target,
|
||||
'target_terminal' => $c->target_terminal,
|
||||
'target_terminal_id' => $c->target_terminal_id,
|
||||
'target_label' => $c->target_label,
|
||||
'connection_type' => $c->connection_type,
|
||||
'color' => $c->getColor(),
|
||||
'output_label' => $c->output_label,
|
||||
'medium_type' => $c->medium_type,
|
||||
'medium_spec' => $c->medium_spec,
|
||||
'medium_length' => $c->medium_length,
|
||||
'is_rail' => $c->is_rail,
|
||||
'fk_carrier' => $c->fk_carrier
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
$response['connections'] = $allConnections;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'clear_all':
|
||||
// Delete all connections for an anlage
|
||||
if (!$user->hasRight('kundenkarte', 'delete')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$anlageId = GETPOSTINT('anlage_id');
|
||||
if ($anlageId > 0) {
|
||||
// Get all carriers for this anlage
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
$carrierObj = new EquipmentCarrier($db);
|
||||
$carriers = $carrierObj->fetchByAnlage($anlageId);
|
||||
|
||||
$deletedCount = 0;
|
||||
foreach ($carriers as $carrier) {
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_connection WHERE fk_carrier = ".((int)$carrier->id);
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
$deletedCount += $db->affected_rows($resql);
|
||||
}
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
$response['deleted_count'] = $deletedCount;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$response['error'] = 'Unknown action';
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
$db->close();
|
||||
201
ajax/equipment_panel.php
Normal file
201
ajax/equipment_panel.php
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* AJAX endpoint for equipment panels (Schaltschrankfelder)
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1');
|
||||
if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
|
||||
if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
|
||||
if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
|
||||
|
||||
$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.'/custom/kundenkarte/class/equipmentpanel.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$panelId = GETPOSTINT('panel_id');
|
||||
$anlageId = GETPOSTINT('anlage_id');
|
||||
|
||||
$panel = new EquipmentPanel($db);
|
||||
|
||||
$response = array('success' => false, 'error' => '');
|
||||
|
||||
// Security check
|
||||
if (!$user->hasRight('kundenkarte', 'read')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'get':
|
||||
// Get single panel data
|
||||
if ($panelId > 0 && $panel->fetch($panelId) > 0) {
|
||||
$response['success'] = true;
|
||||
$response['panel'] = array(
|
||||
'id' => $panel->id,
|
||||
'fk_anlage' => $panel->fk_anlage,
|
||||
'label' => $panel->label,
|
||||
'position' => $panel->position,
|
||||
'note_private' => $panel->note_private,
|
||||
'status' => $panel->status
|
||||
);
|
||||
} else {
|
||||
$response['error'] = 'Panel not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
// List all panels for an Anlage
|
||||
if ($anlageId > 0) {
|
||||
$panels = $panel->fetchByAnlage($anlageId);
|
||||
$result = array();
|
||||
foreach ($panels as $p) {
|
||||
$result[] = array(
|
||||
'id' => $p->id,
|
||||
'fk_anlage' => $p->fk_anlage,
|
||||
'label' => $p->label,
|
||||
'position' => $p->position,
|
||||
'status' => $p->status
|
||||
);
|
||||
}
|
||||
$response['success'] = true;
|
||||
$response['panels'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'create':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
|
||||
$panel->fk_anlage = $anlageId;
|
||||
$panel->label = GETPOST('label', 'alphanohtml');
|
||||
$panel->position = GETPOSTINT('position');
|
||||
$panel->note_private = GETPOST('note_private', 'restricthtml');
|
||||
|
||||
$result = $panel->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['panel_id'] = $result;
|
||||
$response['label'] = $panel->label;
|
||||
} else {
|
||||
$response['error'] = $panel->error;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($panel->fetch($panelId) > 0) {
|
||||
$panel->label = GETPOST('label', 'alphanohtml') ?: $panel->label;
|
||||
$panel->position = GETPOSTINT('position') ?: $panel->position;
|
||||
$panel->note_private = GETPOST('note_private', 'restricthtml');
|
||||
|
||||
$result = $panel->update($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $panel->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Panel not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!$user->hasRight('kundenkarte', 'delete')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($panel->fetch($panelId) > 0) {
|
||||
$result = $panel->delete($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
} else {
|
||||
$response['error'] = $panel->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Panel not found';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list_with_carriers':
|
||||
// List all panels with their carriers for an Anlage
|
||||
if ($anlageId > 0) {
|
||||
$panels = $panel->fetchByAnlage($anlageId);
|
||||
$result = array();
|
||||
|
||||
foreach ($panels as $p) {
|
||||
$panelData = array(
|
||||
'id' => $p->id,
|
||||
'fk_anlage' => $p->fk_anlage,
|
||||
'label' => $p->label,
|
||||
'position' => $p->position,
|
||||
'status' => $p->status,
|
||||
'carriers' => array()
|
||||
);
|
||||
|
||||
// Fetch carriers for this panel
|
||||
$p->fetchCarriers();
|
||||
foreach ($p->carriers as $c) {
|
||||
$panelData['carriers'][] = array(
|
||||
'id' => $c->id,
|
||||
'label' => $c->label,
|
||||
'total_te' => $c->total_te,
|
||||
'position' => $c->position
|
||||
);
|
||||
}
|
||||
|
||||
$result[] = $panelData;
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
$response['panels'] = $result;
|
||||
} else {
|
||||
$response['error'] = 'Missing anlage_id';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
if (!$user->hasRight('kundenkarte', 'write')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
break;
|
||||
}
|
||||
if ($panel->fetch($panelId) > 0) {
|
||||
// Create a copy of the panel
|
||||
$newPanel = new EquipmentPanel($db);
|
||||
$newPanel->fk_anlage = $panel->fk_anlage;
|
||||
$newPanel->label = $panel->label.' (Kopie)';
|
||||
$newPanel->note_private = $panel->note_private;
|
||||
|
||||
$result = $newPanel->create($user);
|
||||
if ($result > 0) {
|
||||
$response['success'] = true;
|
||||
$response['panel_id'] = $result;
|
||||
} else {
|
||||
$response['error'] = $newPanel->error;
|
||||
}
|
||||
} else {
|
||||
$response['error'] = 'Panel not found';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$response['error'] = 'Unknown action';
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
$db->close();
|
||||
74
ajax/equipment_type_fields.php
Normal file
74
ajax/equipment_type_fields.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* AJAX endpoint to get equipment type fields
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1');
|
||||
if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1');
|
||||
if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1');
|
||||
if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1');
|
||||
|
||||
$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.'/custom/kundenkarte/class/equipmenttype.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipment.class.php';
|
||||
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$typeId = GETPOSTINT('type_id');
|
||||
$equipmentId = GETPOSTINT('equipment_id');
|
||||
|
||||
$response = array('success' => false, 'fields' => array());
|
||||
|
||||
if (!$user->hasRight('kundenkarte', 'read')) {
|
||||
$response['error'] = 'Permission denied';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($typeId > 0) {
|
||||
$type = new EquipmentType($db);
|
||||
if ($type->fetch($typeId) > 0) {
|
||||
$fields = $type->fetchFields(1);
|
||||
|
||||
// Get existing values if editing
|
||||
$existingValues = array();
|
||||
if ($equipmentId > 0) {
|
||||
$equipment = new Equipment($db);
|
||||
if ($equipment->fetch($equipmentId) > 0) {
|
||||
$existingValues = $equipment->getFieldValues();
|
||||
}
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($fields as $field) {
|
||||
$value = isset($existingValues[$field->field_code]) ? $existingValues[$field->field_code] : $field->field_default;
|
||||
$result[] = array(
|
||||
'code' => $field->field_code,
|
||||
'label' => $field->field_label,
|
||||
'type' => $field->field_type,
|
||||
'options' => $field->field_options,
|
||||
'required' => $field->required,
|
||||
'show_on_block' => $field->show_on_block,
|
||||
'value' => $value
|
||||
);
|
||||
}
|
||||
|
||||
$response['success'] = true;
|
||||
$response['fields'] = $result;
|
||||
$response['type'] = array(
|
||||
'id' => $type->id,
|
||||
'label' => $type->label,
|
||||
'label_short' => $type->label_short,
|
||||
'width_te' => $type->width_te,
|
||||
'color' => $type->color
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
$db->close();
|
||||
|
|
@ -25,6 +25,7 @@ class AnlageType extends CommonObject
|
|||
public $can_have_children;
|
||||
public $can_be_nested;
|
||||
public $allowed_parent_types;
|
||||
public $can_have_equipment;
|
||||
|
||||
public $picto;
|
||||
public $color;
|
||||
|
|
@ -72,7 +73,7 @@ class AnlageType extends CommonObject
|
|||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, ref, label, label_short, description, fk_system,";
|
||||
$sql .= " can_have_children, can_be_nested, allowed_parent_types,";
|
||||
$sql .= " can_have_children, can_be_nested, allowed_parent_types, can_have_equipment,";
|
||||
$sql .= " picto, color, is_system, position, active,";
|
||||
$sql .= " date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
|
|
@ -85,6 +86,7 @@ class AnlageType extends CommonObject
|
|||
$sql .= ", ".((int) $this->can_have_children);
|
||||
$sql .= ", ".((int) $this->can_be_nested);
|
||||
$sql .= ", ".($this->allowed_parent_types ? "'".$this->db->escape($this->allowed_parent_types)."'" : "NULL");
|
||||
$sql .= ", ".((int) $this->can_have_equipment);
|
||||
$sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
|
||||
$sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", 0"; // is_system = 0 for user-created
|
||||
|
|
@ -141,6 +143,7 @@ class AnlageType extends CommonObject
|
|||
$this->can_have_children = $obj->can_have_children;
|
||||
$this->can_be_nested = $obj->can_be_nested;
|
||||
$this->allowed_parent_types = $obj->allowed_parent_types;
|
||||
$this->can_have_equipment = $obj->can_have_equipment ?? 0;
|
||||
$this->picto = $obj->picto;
|
||||
$this->color = $obj->color;
|
||||
$this->is_system = $obj->is_system;
|
||||
|
|
@ -186,6 +189,7 @@ class AnlageType extends CommonObject
|
|||
$sql .= ", can_have_children = ".((int) $this->can_have_children);
|
||||
$sql .= ", can_be_nested = ".((int) $this->can_be_nested);
|
||||
$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 .= ", picto = ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
|
||||
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", position = ".((int) $this->position);
|
||||
|
|
@ -295,6 +299,7 @@ class AnlageType extends CommonObject
|
|||
$type->can_have_children = $obj->can_have_children;
|
||||
$type->can_be_nested = $obj->can_be_nested;
|
||||
$type->allowed_parent_types = $obj->allowed_parent_types;
|
||||
$type->can_have_equipment = $obj->can_have_equipment ?? 0;
|
||||
$type->picto = $obj->picto;
|
||||
$type->is_system = $obj->is_system;
|
||||
$type->position = $obj->position;
|
||||
|
|
|
|||
494
class/equipment.class.php
Normal file
494
class/equipment.class.php
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmenttype.class.php';
|
||||
|
||||
/**
|
||||
* Class Equipment
|
||||
* Manages equipment instances (Sicherungsautomaten, FI-Schalter, etc.)
|
||||
*/
|
||||
class Equipment extends CommonObject
|
||||
{
|
||||
public $element = 'equipment';
|
||||
public $table_element = 'kundenkarte_equipment';
|
||||
|
||||
public $fk_carrier;
|
||||
public $fk_equipment_type;
|
||||
public $label;
|
||||
public $position_te;
|
||||
public $width_te;
|
||||
public $field_values;
|
||||
public $fk_product;
|
||||
public $fk_protection; // FK to protection device (FI/RCD)
|
||||
public $protection_label; // Label shown above equipment when in protection group
|
||||
public $note_private;
|
||||
public $status;
|
||||
|
||||
public $date_creation;
|
||||
public $fk_user_creat;
|
||||
public $fk_user_modif;
|
||||
|
||||
// Loaded objects
|
||||
public $type; // EquipmentType object
|
||||
public $type_label;
|
||||
public $type_label_short;
|
||||
public $type_color;
|
||||
public $type_picto;
|
||||
public $product_ref;
|
||||
public $product_label;
|
||||
public $protection_device_label; // Label of the protection device
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @return int Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function create($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$error = 0;
|
||||
$now = dol_now();
|
||||
|
||||
if (empty($this->fk_carrier) || empty($this->fk_equipment_type)) {
|
||||
$this->error = 'ErrorMissingParameters';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get default width from type if not set
|
||||
if (empty($this->width_te)) {
|
||||
$type = new EquipmentType($this->db);
|
||||
if ($type->fetch($this->fk_equipment_type) > 0) {
|
||||
$this->width_te = $type->width_te;
|
||||
} else {
|
||||
$this->width_te = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, fk_carrier, fk_equipment_type, label,";
|
||||
$sql .= " position_te, width_te, field_values, fk_product,";
|
||||
$sql .= " fk_protection, protection_label,";
|
||||
$sql .= " note_private, status,";
|
||||
$sql .= " date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= ((int) $conf->entity);
|
||||
$sql .= ", ".((int) $this->fk_carrier);
|
||||
$sql .= ", ".((int) $this->fk_equipment_type);
|
||||
$sql .= ", ".($this->label ? "'".$this->db->escape($this->label)."'" : "NULL");
|
||||
$sql .= ", ".((int) $this->position_te);
|
||||
$sql .= ", ".((int) $this->width_te);
|
||||
$sql .= ", ".($this->field_values ? "'".$this->db->escape($this->field_values)."'" : "NULL");
|
||||
$sql .= ", ".($this->fk_product > 0 ? ((int) $this->fk_product) : "NULL");
|
||||
$sql .= ", ".($this->fk_protection > 0 ? ((int) $this->fk_protection) : "NULL");
|
||||
$sql .= ", ".($this->protection_label ? "'".$this->db->escape($this->protection_label)."'" : "NULL");
|
||||
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", ".((int) ($this->status !== null ? $this->status : 1));
|
||||
$sql .= ", '".$this->db->idate($now)."'";
|
||||
$sql .= ", ".((int) $user->id);
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object from database
|
||||
*
|
||||
* @param int $id ID of record
|
||||
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
$sql = "SELECT e.*, t.label as type_label, t.label_short as type_label_short,";
|
||||
$sql .= " t.color as type_color, t.picto as type_picto,";
|
||||
$sql .= " p.ref as product_ref, p.label as product_label,";
|
||||
$sql .= " prot.label as protection_device_label";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as e";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment_type as t ON e.fk_equipment_type = t.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON e.fk_product = p.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment as prot ON e.fk_protection = prot.rowid";
|
||||
$sql .= " WHERE e.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
if ($this->db->num_rows($resql)) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
|
||||
$this->id = $obj->rowid;
|
||||
$this->entity = $obj->entity;
|
||||
$this->fk_carrier = $obj->fk_carrier;
|
||||
$this->fk_equipment_type = $obj->fk_equipment_type;
|
||||
$this->label = $obj->label;
|
||||
$this->position_te = $obj->position_te;
|
||||
$this->width_te = $obj->width_te;
|
||||
$this->field_values = $obj->field_values;
|
||||
$this->fk_product = $obj->fk_product;
|
||||
$this->fk_protection = $obj->fk_protection;
|
||||
$this->protection_label = $obj->protection_label;
|
||||
$this->note_private = $obj->note_private;
|
||||
$this->status = $obj->status;
|
||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||
$this->fk_user_creat = $obj->fk_user_creat;
|
||||
$this->fk_user_modif = $obj->fk_user_modif;
|
||||
|
||||
$this->type_label = $obj->type_label;
|
||||
$this->type_label_short = $obj->type_label_short;
|
||||
$this->type_color = $obj->type_color;
|
||||
$this->type_picto = $obj->type_picto;
|
||||
$this->product_ref = $obj->product_ref;
|
||||
$this->product_label = $obj->product_label;
|
||||
$this->protection_device_label = $obj->protection_device_label;
|
||||
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
} else {
|
||||
$this->db->free($resql);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in database
|
||||
*
|
||||
* @param User $user User that modifies
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function update($user)
|
||||
{
|
||||
$error = 0;
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
|
||||
$sql .= " fk_equipment_type = ".((int) $this->fk_equipment_type);
|
||||
$sql .= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "NULL");
|
||||
$sql .= ", position_te = ".((int) $this->position_te);
|
||||
$sql .= ", width_te = ".((int) $this->width_te);
|
||||
$sql .= ", field_values = ".($this->field_values ? "'".$this->db->escape($this->field_values)."'" : "NULL");
|
||||
$sql .= ", fk_product = ".($this->fk_product > 0 ? ((int) $this->fk_product) : "NULL");
|
||||
$sql .= ", fk_protection = ".($this->fk_protection > 0 ? ((int) $this->fk_protection) : "NULL");
|
||||
$sql .= ", protection_label = ".($this->protection_label ? "'".$this->db->escape($this->protection_label)."'" : "NULL");
|
||||
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", status = ".((int) $this->status);
|
||||
$sql .= ", fk_user_modif = ".((int) $user->id);
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in database
|
||||
*
|
||||
* @param User $user User that deletes
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
$error = 0;
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all equipment on a carrier
|
||||
*
|
||||
* @param int $carrierId Carrier ID
|
||||
* @param int $activeOnly Only active equipment
|
||||
* @return array Array of Equipment objects
|
||||
*/
|
||||
public function fetchByCarrier($carrierId, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT e.*, t.label as type_label, t.label_short as type_label_short,";
|
||||
$sql .= " t.ref as type_ref, t.color as type_color, t.picto as type_picto,";
|
||||
$sql .= " t.terminals_config as terminals_config,";
|
||||
$sql .= " prot.label as protection_device_label";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as e";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment_type as t ON e.fk_equipment_type = t.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment as prot ON e.fk_protection = prot.rowid";
|
||||
$sql .= " WHERE e.fk_carrier = ".((int) $carrierId);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND e.status = 1";
|
||||
}
|
||||
$sql .= " ORDER BY e.position_te ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$eq = new Equipment($this->db);
|
||||
$eq->id = $obj->rowid;
|
||||
$eq->entity = $obj->entity;
|
||||
$eq->fk_carrier = $obj->fk_carrier;
|
||||
$eq->fk_equipment_type = $obj->fk_equipment_type;
|
||||
$eq->label = $obj->label;
|
||||
$eq->position_te = $obj->position_te;
|
||||
$eq->width_te = $obj->width_te;
|
||||
$eq->field_values = $obj->field_values;
|
||||
$eq->fk_product = $obj->fk_product;
|
||||
$eq->fk_protection = $obj->fk_protection;
|
||||
$eq->protection_label = $obj->protection_label;
|
||||
$eq->note_private = $obj->note_private;
|
||||
$eq->status = $obj->status;
|
||||
|
||||
$eq->type_label = $obj->type_label;
|
||||
$eq->type_label_short = $obj->type_label_short;
|
||||
$eq->type_ref = $obj->type_ref;
|
||||
$eq->type_color = $obj->type_color;
|
||||
$eq->type_picto = $obj->type_picto;
|
||||
$eq->terminals_config = $obj->terminals_config;
|
||||
$eq->protection_device_label = $obj->protection_device_label;
|
||||
|
||||
$results[] = $eq;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch protection devices (FI/RCD) for an Anlage
|
||||
* Protection devices are equipment types that can protect other equipment
|
||||
*
|
||||
* @param int $anlageId Anlage ID
|
||||
* @return array Array of Equipment objects that are protection devices
|
||||
*/
|
||||
public function fetchProtectionDevices($anlageId)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
// Get all equipment for this anlage that have type with is_protection = 1
|
||||
// Or equipment types that are typically protection devices (FI, RCD, etc.)
|
||||
$sql = "SELECT e.*, t.label as type_label, t.label_short as type_label_short,";
|
||||
$sql .= " t.color as type_color, t.ref as type_ref, c.fk_anlage";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as e";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment_type as t ON e.fk_equipment_type = t.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment_carrier as c ON e.fk_carrier = c.rowid";
|
||||
$sql .= " WHERE c.fk_anlage = ".((int) $anlageId);
|
||||
$sql .= " AND e.status = 1";
|
||||
// Filter for protection device types (FI, RCD, FI_LS, etc.)
|
||||
$sql .= " AND (t.ref LIKE '%FI%' OR t.ref LIKE '%RCD%' OR t.ref LIKE 'RCBO%')";
|
||||
$sql .= " ORDER BY c.position ASC, e.position_te ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$eq = new Equipment($this->db);
|
||||
$eq->id = $obj->rowid;
|
||||
$eq->fk_carrier = $obj->fk_carrier;
|
||||
$eq->fk_equipment_type = $obj->fk_equipment_type;
|
||||
$eq->label = $obj->label;
|
||||
$eq->position_te = $obj->position_te;
|
||||
$eq->width_te = $obj->width_te;
|
||||
$eq->type_label = $obj->type_label;
|
||||
$eq->type_label_short = $obj->type_label_short;
|
||||
$eq->type_color = $obj->type_color;
|
||||
|
||||
$results[] = $eq;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate this equipment (for "+" button)
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @param int $carrierId Target carrier (0 = same carrier)
|
||||
* @param int $position Target position (-1 = auto)
|
||||
* @return int Return integer <0 if KO, Id of new object if OK
|
||||
*/
|
||||
public function duplicate($user, $carrierId = 0, $position = -1)
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
|
||||
$newEquipment = new Equipment($this->db);
|
||||
$newEquipment->fk_carrier = $carrierId > 0 ? $carrierId : $this->fk_carrier;
|
||||
$newEquipment->fk_equipment_type = $this->fk_equipment_type;
|
||||
$newEquipment->label = $this->label;
|
||||
$newEquipment->width_te = $this->width_te;
|
||||
$newEquipment->field_values = $this->field_values;
|
||||
$newEquipment->fk_product = $this->fk_product;
|
||||
$newEquipment->note_private = $this->note_private;
|
||||
$newEquipment->status = 1;
|
||||
|
||||
// Find position
|
||||
if ($position >= 0) {
|
||||
$newEquipment->position_te = $position;
|
||||
} else {
|
||||
// Auto-find next position after this equipment
|
||||
$carrier = new EquipmentCarrier($this->db);
|
||||
$carrier->fetch($newEquipment->fk_carrier);
|
||||
$carrier->fetchEquipment();
|
||||
|
||||
// Try position right after this element
|
||||
$tryPos = $this->position_te + $this->width_te;
|
||||
if ($carrier->isPositionAvailable($tryPos, $this->width_te)) {
|
||||
$newEquipment->position_te = $tryPos;
|
||||
} else {
|
||||
// Find any free position
|
||||
$newEquipment->position_te = $carrier->getNextFreePosition($this->width_te);
|
||||
if ($newEquipment->position_te < 0) {
|
||||
$this->error = 'ErrorNoSpaceOnCarrier';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $newEquipment->create($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field values as array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFieldValues()
|
||||
{
|
||||
if (empty($this->field_values)) {
|
||||
return array();
|
||||
}
|
||||
$values = json_decode($this->field_values, true);
|
||||
return is_array($values) ? $values : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set field values from array
|
||||
*
|
||||
* @param array $values Key-value pairs
|
||||
* @return void
|
||||
*/
|
||||
public function setFieldValues($values)
|
||||
{
|
||||
$this->field_values = json_encode($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single field value
|
||||
*
|
||||
* @param string $fieldCode Field code
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getFieldValue($fieldCode)
|
||||
{
|
||||
$values = $this->getFieldValues();
|
||||
return isset($values[$fieldCode]) ? $values[$fieldCode] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get label for SVG block display
|
||||
* Combines fields with show_on_block = 1
|
||||
*
|
||||
* @return string Label to display on block (e.g. "B16")
|
||||
*/
|
||||
public function getBlockLabel()
|
||||
{
|
||||
$type = new EquipmentType($this->db);
|
||||
if ($type->fetch($this->fk_equipment_type) <= 0) {
|
||||
return $this->type_label_short ?: '';
|
||||
}
|
||||
|
||||
$blockFields = $type->getBlockFields();
|
||||
if (empty($blockFields)) {
|
||||
return $this->type_label_short ?: '';
|
||||
}
|
||||
|
||||
$values = $this->getFieldValues();
|
||||
$parts = array();
|
||||
|
||||
foreach ($blockFields as $field) {
|
||||
if (isset($values[$field->field_code]) && $values[$field->field_code] !== '') {
|
||||
$parts[] = $values[$field->field_code];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($parts)) {
|
||||
return $this->type_label_short ?: '';
|
||||
}
|
||||
|
||||
return implode('', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color for SVG block
|
||||
*
|
||||
* @return string Hex color code
|
||||
*/
|
||||
public function getBlockColor()
|
||||
{
|
||||
if (!empty($this->type_color)) {
|
||||
return $this->type_color;
|
||||
}
|
||||
|
||||
// Default color
|
||||
return '#3498db';
|
||||
}
|
||||
}
|
||||
426
class/equipmentcarrier.class.php
Normal file
426
class/equipmentcarrier.class.php
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class EquipmentCarrier
|
||||
* Manages equipment carriers (Hutschienen/Traeger)
|
||||
*/
|
||||
class EquipmentCarrier extends CommonObject
|
||||
{
|
||||
public $element = 'equipmentcarrier';
|
||||
public $table_element = 'kundenkarte_equipment_carrier';
|
||||
|
||||
public $fk_anlage;
|
||||
public $fk_panel;
|
||||
public $label;
|
||||
public $total_te = 12;
|
||||
public $position;
|
||||
public $note_private;
|
||||
public $status;
|
||||
|
||||
public $date_creation;
|
||||
public $fk_user_creat;
|
||||
public $fk_user_modif;
|
||||
|
||||
// Loaded objects
|
||||
public $equipment = array();
|
||||
public $anlage_label;
|
||||
public $panel_label;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @return int Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function create($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$error = 0;
|
||||
$now = dol_now();
|
||||
|
||||
if (empty($this->fk_anlage) || empty($this->label)) {
|
||||
$this->error = 'ErrorMissingParameters';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get next position
|
||||
if (empty($this->position)) {
|
||||
$sql = "SELECT MAX(position) as maxpos FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_anlage = ".((int) $this->fk_anlage);
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
$this->position = ($obj->maxpos !== null) ? $obj->maxpos + 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, fk_anlage, fk_panel, label, total_te, position, note_private, status,";
|
||||
$sql .= " date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= ((int) $conf->entity);
|
||||
$sql .= ", ".((int) $this->fk_anlage);
|
||||
$sql .= ", ".($this->fk_panel > 0 ? ((int) $this->fk_panel) : "NULL");
|
||||
$sql .= ", '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", ".((int) ($this->total_te > 0 ? $this->total_te : 12));
|
||||
$sql .= ", ".((int) $this->position);
|
||||
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", ".((int) ($this->status !== null ? $this->status : 1));
|
||||
$sql .= ", '".$this->db->idate($now)."'";
|
||||
$sql .= ", ".((int) $user->id);
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object from database
|
||||
*
|
||||
* @param int $id ID of record
|
||||
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
$sql = "SELECT c.*, a.label as anlage_label, p.label as panel_label";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as c";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_anlage as a ON c.fk_anlage = a.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_equipment_panel as p ON c.fk_panel = p.rowid";
|
||||
$sql .= " WHERE c.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
if ($this->db->num_rows($resql)) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
|
||||
$this->id = $obj->rowid;
|
||||
$this->entity = $obj->entity;
|
||||
$this->fk_anlage = $obj->fk_anlage;
|
||||
$this->fk_panel = $obj->fk_panel;
|
||||
$this->label = $obj->label;
|
||||
$this->total_te = $obj->total_te;
|
||||
$this->position = $obj->position;
|
||||
$this->note_private = $obj->note_private;
|
||||
$this->status = $obj->status;
|
||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||
$this->fk_user_creat = $obj->fk_user_creat;
|
||||
$this->fk_user_modif = $obj->fk_user_modif;
|
||||
|
||||
$this->anlage_label = $obj->anlage_label;
|
||||
$this->panel_label = $obj->panel_label;
|
||||
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
} else {
|
||||
$this->db->free($resql);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in database
|
||||
*
|
||||
* @param User $user User that modifies
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function update($user)
|
||||
{
|
||||
$error = 0;
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
|
||||
$sql .= " label = '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", fk_panel = ".($this->fk_panel > 0 ? ((int) $this->fk_panel) : "NULL");
|
||||
$sql .= ", total_te = ".((int) ($this->total_te > 0 ? $this->total_te : 12));
|
||||
$sql .= ", position = ".((int) $this->position);
|
||||
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", status = ".((int) $this->status);
|
||||
$sql .= ", fk_user_modif = ".((int) $user->id);
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in database
|
||||
*
|
||||
* @param User $user User that deletes
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
$error = 0;
|
||||
$this->db->begin();
|
||||
|
||||
// Equipment is deleted via CASCADE
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all carriers for a Panel
|
||||
*
|
||||
* @param int $panelId Panel ID
|
||||
* @param int $activeOnly Only active carriers
|
||||
* @return array Array of EquipmentCarrier objects
|
||||
*/
|
||||
public function fetchByPanel($panelId, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_panel = ".((int) $panelId);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND status = 1";
|
||||
}
|
||||
$sql .= " ORDER BY position ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$carrier = new EquipmentCarrier($this->db);
|
||||
$carrier->id = $obj->rowid;
|
||||
$carrier->entity = $obj->entity;
|
||||
$carrier->fk_anlage = $obj->fk_anlage;
|
||||
$carrier->fk_panel = $obj->fk_panel;
|
||||
$carrier->label = $obj->label;
|
||||
$carrier->total_te = $obj->total_te;
|
||||
$carrier->position = $obj->position;
|
||||
$carrier->note_private = $obj->note_private;
|
||||
$carrier->status = $obj->status;
|
||||
|
||||
$results[] = $carrier;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all carriers for an Anlage
|
||||
*
|
||||
* @param int $anlageId Anlage ID
|
||||
* @param int $activeOnly Only active carriers
|
||||
* @return array Array of EquipmentCarrier objects
|
||||
*/
|
||||
public function fetchByAnlage($anlageId, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_anlage = ".((int) $anlageId);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND status = 1";
|
||||
}
|
||||
$sql .= " ORDER BY position ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$carrier = new EquipmentCarrier($this->db);
|
||||
$carrier->id = $obj->rowid;
|
||||
$carrier->entity = $obj->entity;
|
||||
$carrier->fk_anlage = $obj->fk_anlage;
|
||||
$carrier->fk_panel = $obj->fk_panel;
|
||||
$carrier->label = $obj->label;
|
||||
$carrier->total_te = $obj->total_te;
|
||||
$carrier->position = $obj->position;
|
||||
$carrier->note_private = $obj->note_private;
|
||||
$carrier->status = $obj->status;
|
||||
|
||||
$results[] = $carrier;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all equipment on this carrier
|
||||
*
|
||||
* @return array Array of Equipment objects
|
||||
*/
|
||||
public function fetchEquipment()
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipment.class.php';
|
||||
|
||||
$equipment = new Equipment($this->db);
|
||||
$this->equipment = $equipment->fetchByCarrier($this->id);
|
||||
|
||||
return $this->equipment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of occupied TE slots
|
||||
*
|
||||
* @return array Array of occupied slot numbers (0-based)
|
||||
*/
|
||||
public function getOccupiedSlots()
|
||||
{
|
||||
$occupied = array();
|
||||
|
||||
if (empty($this->equipment)) {
|
||||
$this->fetchEquipment();
|
||||
}
|
||||
|
||||
foreach ($this->equipment as $eq) {
|
||||
for ($i = $eq->position_te; $i < $eq->position_te + $eq->width_te; $i++) {
|
||||
$occupied[] = $i;
|
||||
}
|
||||
}
|
||||
|
||||
return $occupied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get used TE count
|
||||
*
|
||||
* @return int Number of used TE
|
||||
*/
|
||||
public function getUsedTE()
|
||||
{
|
||||
return count($this->getOccupiedSlots());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get free TE count
|
||||
*
|
||||
* @return int Number of free TE
|
||||
*/
|
||||
public function getFreeTE()
|
||||
{
|
||||
return $this->total_te - $this->getUsedTE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find next free position for given width
|
||||
*
|
||||
* @param int $width Width in TE needed
|
||||
* @return int Position (1-based) or -1 if no space
|
||||
*/
|
||||
public function getNextFreePosition($width = 1)
|
||||
{
|
||||
$occupied = $this->getOccupiedSlots();
|
||||
|
||||
// Positions are 1-based (1 to total_te)
|
||||
for ($pos = 1; $pos <= $this->total_te - $width + 1; $pos++) {
|
||||
$fits = true;
|
||||
for ($i = $pos; $i < $pos + $width; $i++) {
|
||||
if (in_array($i, $occupied)) {
|
||||
$fits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($fits) {
|
||||
return $pos;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // No space available
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if position is available for given width
|
||||
*
|
||||
* @param int $position Start position (1-based)
|
||||
* @param int $width Width in TE
|
||||
* @param int $excludeEquipmentId Equipment ID to exclude (for updates)
|
||||
* @return bool True if position is available
|
||||
*/
|
||||
public function isPositionAvailable($position, $width, $excludeEquipmentId = 0)
|
||||
{
|
||||
// Check bounds (positions are 1-based)
|
||||
if ($position < 1 || $position + $width - 1 > $this->total_te) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($this->equipment)) {
|
||||
$this->fetchEquipment();
|
||||
}
|
||||
|
||||
foreach ($this->equipment as $eq) {
|
||||
if ($excludeEquipmentId > 0 && $eq->id == $excludeEquipmentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for overlap
|
||||
$eqStart = $eq->position_te;
|
||||
$eqEnd = $eq->position_te + $eq->width_te - 1;
|
||||
$newStart = $position;
|
||||
$newEnd = $position + $width - 1;
|
||||
|
||||
if ($newStart <= $eqEnd && $newEnd >= $eqStart) {
|
||||
return false; // Overlap
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
419
class/equipmentconnection.class.php
Normal file
419
class/equipmentconnection.class.php
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class EquipmentConnection
|
||||
* Manages connections between equipment (generic for all system types)
|
||||
*/
|
||||
class EquipmentConnection extends CommonObject
|
||||
{
|
||||
public $element = 'equipmentconnection';
|
||||
public $table_element = 'kundenkarte_equipment_connection';
|
||||
|
||||
public $fk_source;
|
||||
public $source_terminal = 'output';
|
||||
public $source_terminal_id;
|
||||
public $fk_target;
|
||||
public $target_terminal = 'input';
|
||||
public $target_terminal_id;
|
||||
|
||||
// Connection properties
|
||||
public $connection_type;
|
||||
public $color;
|
||||
|
||||
// Output/endpoint info
|
||||
public $output_label;
|
||||
|
||||
// Medium info (cable, wire, etc.)
|
||||
public $medium_type;
|
||||
public $medium_spec;
|
||||
public $medium_length;
|
||||
|
||||
// Rail info
|
||||
public $is_rail = 0;
|
||||
public $rail_start_te;
|
||||
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 $fk_carrier;
|
||||
public $position_y = 0;
|
||||
public $note_private;
|
||||
public $status = 1;
|
||||
|
||||
public $date_creation;
|
||||
public $fk_user_creat;
|
||||
public $fk_user_modif;
|
||||
|
||||
// Loaded objects
|
||||
public $source_label;
|
||||
public $target_label;
|
||||
public $carrier_label;
|
||||
public $source_pos;
|
||||
public $source_width;
|
||||
public $target_pos;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @return int Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function create($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$error = 0;
|
||||
$now = dol_now();
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, fk_source, source_terminal, source_terminal_id, 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,";
|
||||
$sql .= " note_private, status, date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= ((int) $conf->entity);
|
||||
$sql .= ", ".($this->fk_source > 0 ? ((int) $this->fk_source) : "NULL");
|
||||
$sql .= ", '".$this->db->escape($this->source_terminal ?: 'output')."'";
|
||||
$sql .= ", ".($this->source_terminal_id ? "'".$this->db->escape($this->source_terminal_id)."'" : "NULL");
|
||||
$sql .= ", ".($this->fk_target > 0 ? ((int) $this->fk_target) : "NULL");
|
||||
$sql .= ", '".$this->db->escape($this->target_terminal ?: 'input')."'";
|
||||
$sql .= ", ".($this->target_terminal_id ? "'".$this->db->escape($this->target_terminal_id)."'" : "NULL");
|
||||
$sql .= ", ".($this->connection_type ? "'".$this->db->escape($this->connection_type)."'" : "NULL");
|
||||
$sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", ".($this->output_label ? "'".$this->db->escape($this->output_label)."'" : "NULL");
|
||||
$sql .= ", ".($this->medium_type ? "'".$this->db->escape($this->medium_type)."'" : "NULL");
|
||||
$sql .= ", ".($this->medium_spec ? "'".$this->db->escape($this->medium_spec)."'" : "NULL");
|
||||
$sql .= ", ".($this->medium_length ? "'".$this->db->escape($this->medium_length)."'" : "NULL");
|
||||
$sql .= ", ".((int) $this->is_rail);
|
||||
$sql .= ", ".($this->rail_start_te > 0 ? ((int) $this->rail_start_te) : "NULL");
|
||||
$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 .= ", ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
|
||||
$sql .= ", ".((int) $this->position_y);
|
||||
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", ".((int) $this->status);
|
||||
$sql .= ", '".$this->db->idate($now)."'";
|
||||
$sql .= ", ".((int) $user->id);
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object from database
|
||||
*
|
||||
* @param int $id ID of record
|
||||
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
$sql = "SELECT c.*, ";
|
||||
$sql .= " src.label as source_label, tgt.label as target_label, car.label as carrier_label";
|
||||
$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_equipment_carrier as car ON c.fk_carrier = car.rowid";
|
||||
$sql .= " WHERE c.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
if ($this->db->num_rows($resql)) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
|
||||
$this->id = $obj->rowid;
|
||||
$this->entity = $obj->entity;
|
||||
$this->fk_source = $obj->fk_source;
|
||||
$this->source_terminal = $obj->source_terminal;
|
||||
$this->source_terminal_id = $obj->source_terminal_id;
|
||||
$this->fk_target = $obj->fk_target;
|
||||
$this->target_terminal = $obj->target_terminal;
|
||||
$this->target_terminal_id = $obj->target_terminal_id;
|
||||
$this->connection_type = $obj->connection_type;
|
||||
$this->color = $obj->color;
|
||||
$this->output_label = $obj->output_label;
|
||||
$this->medium_type = $obj->medium_type;
|
||||
$this->medium_spec = $obj->medium_spec;
|
||||
$this->medium_length = $obj->medium_length;
|
||||
$this->is_rail = $obj->is_rail;
|
||||
$this->rail_start_te = $obj->rail_start_te;
|
||||
$this->rail_end_te = $obj->rail_end_te;
|
||||
$this->rail_phases = $obj->rail_phases;
|
||||
$this->excluded_te = $obj->excluded_te;
|
||||
$this->fk_carrier = $obj->fk_carrier;
|
||||
$this->position_y = $obj->position_y;
|
||||
$this->note_private = $obj->note_private;
|
||||
$this->status = $obj->status;
|
||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||
$this->fk_user_creat = $obj->fk_user_creat;
|
||||
$this->fk_user_modif = $obj->fk_user_modif;
|
||||
|
||||
$this->source_label = $obj->source_label;
|
||||
$this->target_label = $obj->target_label;
|
||||
$this->carrier_label = $obj->carrier_label;
|
||||
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
} else {
|
||||
$this->db->free($resql);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in database
|
||||
*
|
||||
* @param User $user User that modifies
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function update($user)
|
||||
{
|
||||
$error = 0;
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
|
||||
$sql .= " fk_source = ".($this->fk_source > 0 ? ((int) $this->fk_source) : "NULL");
|
||||
$sql .= ", source_terminal = '".$this->db->escape($this->source_terminal ?: 'output')."'";
|
||||
$sql .= ", fk_target = ".($this->fk_target > 0 ? ((int) $this->fk_target) : "NULL");
|
||||
$sql .= ", target_terminal = '".$this->db->escape($this->target_terminal ?: 'input')."'";
|
||||
$sql .= ", connection_type = ".($this->connection_type ? "'".$this->db->escape($this->connection_type)."'" : "NULL");
|
||||
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", output_label = ".($this->output_label ? "'".$this->db->escape($this->output_label)."'" : "NULL");
|
||||
$sql .= ", medium_type = ".($this->medium_type ? "'".$this->db->escape($this->medium_type)."'" : "NULL");
|
||||
$sql .= ", medium_spec = ".($this->medium_spec ? "'".$this->db->escape($this->medium_spec)."'" : "NULL");
|
||||
$sql .= ", medium_length = ".($this->medium_length ? "'".$this->db->escape($this->medium_length)."'" : "NULL");
|
||||
$sql .= ", is_rail = ".((int) $this->is_rail);
|
||||
$sql .= ", rail_start_te = ".($this->rail_start_te > 0 ? ((int) $this->rail_start_te) : "NULL");
|
||||
$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_carrier = ".($this->fk_carrier > 0 ? ((int) $this->fk_carrier) : "NULL");
|
||||
$sql .= ", position_y = ".((int) $this->position_y);
|
||||
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", status = ".((int) $this->status);
|
||||
$sql .= ", fk_user_modif = ".((int) $user->id);
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in database
|
||||
*
|
||||
* @param User $user User that deletes
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
$error = 0;
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all connections for a carrier
|
||||
*
|
||||
* @param int $carrierId Carrier ID
|
||||
* @param int $activeOnly Only active connections
|
||||
* @return array Array of EquipmentConnection objects
|
||||
*/
|
||||
public function fetchByCarrier($carrierId, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$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 .= " 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 .= " WHERE c.fk_carrier = ".((int) $carrierId);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND c.status = 1";
|
||||
}
|
||||
$sql .= " ORDER BY c.position_y ASC, c.rowid ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$conn = new EquipmentConnection($this->db);
|
||||
$conn->id = $obj->rowid;
|
||||
$conn->entity = $obj->entity;
|
||||
$conn->fk_source = $obj->fk_source;
|
||||
$conn->source_terminal = $obj->source_terminal;
|
||||
$conn->source_terminal_id = $obj->source_terminal_id;
|
||||
$conn->fk_target = $obj->fk_target;
|
||||
$conn->target_terminal = $obj->target_terminal;
|
||||
$conn->target_terminal_id = $obj->target_terminal_id;
|
||||
$conn->connection_type = $obj->connection_type;
|
||||
$conn->color = $obj->color;
|
||||
$conn->output_label = $obj->output_label;
|
||||
$conn->medium_type = $obj->medium_type;
|
||||
$conn->medium_spec = $obj->medium_spec;
|
||||
$conn->medium_length = $obj->medium_length;
|
||||
$conn->is_rail = $obj->is_rail;
|
||||
$conn->rail_start_te = $obj->rail_start_te;
|
||||
$conn->rail_end_te = $obj->rail_end_te;
|
||||
$conn->rail_phases = $obj->rail_phases;
|
||||
$conn->excluded_te = $obj->excluded_te;
|
||||
$conn->fk_carrier = $obj->fk_carrier;
|
||||
$conn->position_y = $obj->position_y;
|
||||
$conn->status = $obj->status;
|
||||
|
||||
$conn->source_label = $obj->source_label;
|
||||
$conn->source_pos = $obj->source_pos;
|
||||
$conn->source_width = $obj->source_width;
|
||||
$conn->target_label = $obj->target_label;
|
||||
$conn->target_pos = $obj->target_pos;
|
||||
|
||||
$results[] = $conn;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all outputs for an equipment
|
||||
*
|
||||
* @param int $equipmentId Equipment ID
|
||||
* @return array Array of EquipmentConnection objects
|
||||
*/
|
||||
public function fetchOutputs($equipmentId)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_source = ".((int) $equipmentId);
|
||||
$sql .= " AND fk_target IS NULL";
|
||||
$sql .= " AND status = 1";
|
||||
$sql .= " ORDER BY position_y ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$conn = new EquipmentConnection($this->db);
|
||||
$conn->id = $obj->rowid;
|
||||
$conn->fk_source = $obj->fk_source;
|
||||
$conn->connection_type = $obj->connection_type;
|
||||
$conn->color = $obj->color;
|
||||
$conn->output_label = $obj->output_label;
|
||||
$conn->medium_type = $obj->medium_type;
|
||||
$conn->medium_spec = $obj->medium_spec;
|
||||
$conn->medium_length = $obj->medium_length;
|
||||
$conn->fk_carrier = $obj->fk_carrier;
|
||||
$conn->position_y = $obj->position_y;
|
||||
$conn->status = $obj->status;
|
||||
|
||||
$results[] = $conn;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display color
|
||||
*
|
||||
* @return string Color hex code
|
||||
*/
|
||||
public function getColor()
|
||||
{
|
||||
if (!empty($this->color)) {
|
||||
return $this->color;
|
||||
}
|
||||
return '#888888'; // Default grey
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display label for output
|
||||
*
|
||||
* @return string Display label
|
||||
*/
|
||||
public function getDisplayLabel()
|
||||
{
|
||||
$parts = array();
|
||||
|
||||
if ($this->output_label) {
|
||||
$parts[] = $this->output_label;
|
||||
}
|
||||
if ($this->medium_type) {
|
||||
$mediumInfo = $this->medium_type;
|
||||
if ($this->medium_spec) {
|
||||
$mediumInfo .= ' '.$this->medium_spec;
|
||||
}
|
||||
$parts[] = $mediumInfo;
|
||||
}
|
||||
|
||||
return implode(' - ', $parts);
|
||||
}
|
||||
}
|
||||
285
class/equipmentpanel.class.php
Normal file
285
class/equipmentpanel.class.php
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class EquipmentPanel
|
||||
* Manages equipment panels (Schaltschrankfelder)
|
||||
* Physical sections in distribution boards containing carriers
|
||||
*/
|
||||
class EquipmentPanel extends CommonObject
|
||||
{
|
||||
public $element = 'equipmentpanel';
|
||||
public $table_element = 'kundenkarte_equipment_panel';
|
||||
|
||||
public $fk_anlage;
|
||||
public $label;
|
||||
public $position;
|
||||
public $note_private;
|
||||
public $status;
|
||||
|
||||
public $date_creation;
|
||||
public $fk_user_creat;
|
||||
public $fk_user_modif;
|
||||
|
||||
// Loaded objects
|
||||
public $carriers = array();
|
||||
public $anlage_label;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @return int Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function create($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$error = 0;
|
||||
$now = dol_now();
|
||||
|
||||
if (empty($this->fk_anlage)) {
|
||||
$this->error = 'ErrorMissingParameters';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get next position
|
||||
if (empty($this->position)) {
|
||||
$sql = "SELECT MAX(position) as maxpos FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_anlage = ".((int) $this->fk_anlage);
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
$this->position = ($obj->maxpos !== null) ? $obj->maxpos + 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Default label if not set
|
||||
if (empty($this->label)) {
|
||||
$this->label = 'Feld '.($this->position + 1);
|
||||
}
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, fk_anlage, label, position, note_private, status,";
|
||||
$sql .= " date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= ((int) $conf->entity);
|
||||
$sql .= ", ".((int) $this->fk_anlage);
|
||||
$sql .= ", '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", ".((int) $this->position);
|
||||
$sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", ".((int) ($this->status !== null ? $this->status : 1));
|
||||
$sql .= ", '".$this->db->idate($now)."'";
|
||||
$sql .= ", ".((int) $user->id);
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object from database
|
||||
*
|
||||
* @param int $id ID of record
|
||||
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
$sql = "SELECT p.*, a.label as anlage_label";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as p";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."kundenkarte_anlage as a ON p.fk_anlage = a.rowid";
|
||||
$sql .= " WHERE p.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
if ($this->db->num_rows($resql)) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
|
||||
$this->id = $obj->rowid;
|
||||
$this->entity = $obj->entity;
|
||||
$this->fk_anlage = $obj->fk_anlage;
|
||||
$this->label = $obj->label;
|
||||
$this->position = $obj->position;
|
||||
$this->note_private = $obj->note_private;
|
||||
$this->status = $obj->status;
|
||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||
$this->fk_user_creat = $obj->fk_user_creat;
|
||||
$this->fk_user_modif = $obj->fk_user_modif;
|
||||
|
||||
$this->anlage_label = $obj->anlage_label;
|
||||
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
} else {
|
||||
$this->db->free($resql);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in database
|
||||
*
|
||||
* @param User $user User that modifies
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function update($user)
|
||||
{
|
||||
$error = 0;
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
|
||||
$sql .= " label = '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", position = ".((int) $this->position);
|
||||
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
||||
$sql .= ", status = ".((int) $this->status);
|
||||
$sql .= ", fk_user_modif = ".((int) $user->id);
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in database
|
||||
*
|
||||
* @param User $user User that deletes
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
$error = 0;
|
||||
$this->db->begin();
|
||||
|
||||
// Carriers are deleted via CASCADE or need to be reassigned
|
||||
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all panels for an Anlage
|
||||
*
|
||||
* @param int $anlageId Anlage ID
|
||||
* @param int $activeOnly Only active panels
|
||||
* @return array Array of EquipmentPanel objects
|
||||
*/
|
||||
public function fetchByAnlage($anlageId, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
|
||||
$sql .= " WHERE fk_anlage = ".((int) $anlageId);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND status = 1";
|
||||
}
|
||||
$sql .= " ORDER BY position ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$panel = new EquipmentPanel($this->db);
|
||||
$panel->id = $obj->rowid;
|
||||
$panel->entity = $obj->entity;
|
||||
$panel->fk_anlage = $obj->fk_anlage;
|
||||
$panel->label = $obj->label;
|
||||
$panel->position = $obj->position;
|
||||
$panel->note_private = $obj->note_private;
|
||||
$panel->status = $obj->status;
|
||||
|
||||
$results[] = $panel;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all carriers in this panel
|
||||
*
|
||||
* @return array Array of EquipmentCarrier objects
|
||||
*/
|
||||
public function fetchCarriers()
|
||||
{
|
||||
require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php';
|
||||
|
||||
$carrier = new EquipmentCarrier($this->db);
|
||||
$this->carriers = $carrier->fetchByPanel($this->id);
|
||||
|
||||
return $this->carriers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total carriers count
|
||||
*
|
||||
* @return int Number of carriers
|
||||
*/
|
||||
public function getCarrierCount()
|
||||
{
|
||||
if (empty($this->carriers)) {
|
||||
$this->fetchCarriers();
|
||||
}
|
||||
return count($this->carriers);
|
||||
}
|
||||
}
|
||||
374
class/equipmenttype.class.php
Normal file
374
class/equipmenttype.class.php
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
<?php
|
||||
/* Copyright (C) 2026 Alles Watt lauft
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class EquipmentType
|
||||
* Manages equipment type templates (Hutschienen-Komponenten)
|
||||
*/
|
||||
class EquipmentType extends CommonObject
|
||||
{
|
||||
public $element = 'equipmenttype';
|
||||
public $table_element = 'kundenkarte_equipment_type';
|
||||
|
||||
public $ref;
|
||||
public $label;
|
||||
public $label_short;
|
||||
public $description;
|
||||
public $fk_system;
|
||||
|
||||
// Equipment-spezifische Felder
|
||||
public $width_te = 1;
|
||||
public $color;
|
||||
public $fk_product;
|
||||
public $terminals_config; // JSON config for terminals
|
||||
|
||||
public $picto;
|
||||
public $is_system;
|
||||
public $position;
|
||||
public $active;
|
||||
|
||||
public $date_creation;
|
||||
public $fk_user_creat;
|
||||
public $fk_user_modif;
|
||||
|
||||
// Loaded objects
|
||||
public $system_label;
|
||||
public $system_code;
|
||||
public $product; // Linked product object
|
||||
public $fields = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create object in database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @return int Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function create($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$error = 0;
|
||||
$now = dol_now();
|
||||
|
||||
if (empty($this->ref) || empty($this->label) || empty($this->fk_system)) {
|
||||
$this->error = 'ErrorMissingParameters';
|
||||
return -1;
|
||||
}
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
|
||||
$sql .= "entity, ref, label, label_short, description, fk_system,";
|
||||
$sql .= " width_te, color, fk_product, terminals_config,";
|
||||
$sql .= " picto, is_system, position, active,";
|
||||
$sql .= " date_creation, fk_user_creat";
|
||||
$sql .= ") VALUES (";
|
||||
$sql .= "0"; // entity 0 = global
|
||||
$sql .= ", '".$this->db->escape($this->ref)."'";
|
||||
$sql .= ", '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", ".($this->label_short ? "'".$this->db->escape($this->label_short)."'" : "NULL");
|
||||
$sql .= ", ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL");
|
||||
$sql .= ", ".((int) $this->fk_system);
|
||||
$sql .= ", ".((int) ($this->width_te > 0 ? $this->width_te : 1));
|
||||
$sql .= ", ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", ".($this->fk_product > 0 ? ((int) $this->fk_product) : "NULL");
|
||||
$sql .= ", ".($this->terminals_config ? "'".$this->db->escape($this->terminals_config)."'" : "NULL");
|
||||
$sql .= ", ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
|
||||
$sql .= ", 0"; // is_system = 0 for user-created
|
||||
$sql .= ", ".((int) $this->position);
|
||||
$sql .= ", ".((int) ($this->active !== null ? $this->active : 1));
|
||||
$sql .= ", '".$this->db->idate($now)."'";
|
||||
$sql .= ", ".((int) $user->id);
|
||||
$sql .= ")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object from database
|
||||
*
|
||||
* @param int $id ID of record
|
||||
* @return int Return integer <0 if KO, 0 if not found, >0 if OK
|
||||
*/
|
||||
public function fetch($id)
|
||||
{
|
||||
$sql = "SELECT t.*, s.label as system_label, s.code as system_code,";
|
||||
$sql .= " p.ref as product_ref, p.label as product_label";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system as s ON t.fk_system = s.rowid";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON t.fk_product = p.rowid";
|
||||
$sql .= " WHERE t.rowid = ".((int) $id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
if ($this->db->num_rows($resql)) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
|
||||
$this->id = $obj->rowid;
|
||||
$this->entity = $obj->entity;
|
||||
$this->ref = $obj->ref;
|
||||
$this->label = $obj->label;
|
||||
$this->label_short = $obj->label_short;
|
||||
$this->description = $obj->description;
|
||||
$this->fk_system = $obj->fk_system;
|
||||
$this->width_te = $obj->width_te;
|
||||
$this->color = $obj->color;
|
||||
$this->fk_product = $obj->fk_product;
|
||||
$this->terminals_config = $obj->terminals_config;
|
||||
$this->picto = $obj->picto;
|
||||
$this->is_system = $obj->is_system;
|
||||
$this->position = $obj->position;
|
||||
$this->active = $obj->active;
|
||||
$this->date_creation = $this->db->jdate($obj->date_creation);
|
||||
$this->fk_user_creat = $obj->fk_user_creat;
|
||||
$this->fk_user_modif = $obj->fk_user_modif;
|
||||
|
||||
$this->system_label = $obj->system_label;
|
||||
$this->system_code = $obj->system_code;
|
||||
$this->product_ref = $obj->product_ref;
|
||||
$this->product_label = $obj->product_label;
|
||||
|
||||
$this->db->free($resql);
|
||||
return 1;
|
||||
} else {
|
||||
$this->db->free($resql);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object in database
|
||||
*
|
||||
* @param User $user User that modifies
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function update($user)
|
||||
{
|
||||
$error = 0;
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET";
|
||||
$sql .= " ref = '".$this->db->escape($this->ref)."'";
|
||||
$sql .= ", label = '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", label_short = ".($this->label_short ? "'".$this->db->escape($this->label_short)."'" : "NULL");
|
||||
$sql .= ", description = ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL");
|
||||
$sql .= ", fk_system = ".((int) $this->fk_system);
|
||||
$sql .= ", width_te = ".((int) ($this->width_te > 0 ? $this->width_te : 1));
|
||||
$sql .= ", color = ".($this->color ? "'".$this->db->escape($this->color)."'" : "NULL");
|
||||
$sql .= ", fk_product = ".($this->fk_product > 0 ? ((int) $this->fk_product) : "NULL");
|
||||
$sql .= ", terminals_config = ".($this->terminals_config ? "'".$this->db->escape($this->terminals_config)."'" : "NULL");
|
||||
$sql .= ", picto = ".($this->picto ? "'".$this->db->escape($this->picto)."'" : "NULL");
|
||||
$sql .= ", position = ".((int) $this->position);
|
||||
$sql .= ", active = ".((int) $this->active);
|
||||
$sql .= ", fk_user_modif = ".((int) $user->id);
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object in database
|
||||
*
|
||||
* @param User $user User that deletes
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
// Check if type is in use
|
||||
$sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."kundenkarte_equipment";
|
||||
$sql .= " WHERE fk_equipment_type = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
if ($obj->cnt > 0) {
|
||||
$this->error = 'ErrorTypeInUse';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot delete system types
|
||||
if ($this->is_system) {
|
||||
$this->error = 'ErrorCannotDeleteSystemType';
|
||||
return -2;
|
||||
}
|
||||
|
||||
$error = 0;
|
||||
$this->db->begin();
|
||||
|
||||
// Delete fields first
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field WHERE fk_equipment_type = ".((int) $this->id);
|
||||
$this->db->query($sql);
|
||||
|
||||
// Delete type
|
||||
$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$error++;
|
||||
$this->errors[] = "Error ".$this->db->lasterror();
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->db->rollback();
|
||||
return -1 * $error;
|
||||
} else {
|
||||
$this->db->commit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all equipment types for a system
|
||||
*
|
||||
* @param int $systemId System ID (0 = all)
|
||||
* @param int $activeOnly Only active types
|
||||
* @return array Array of EquipmentType objects
|
||||
*/
|
||||
public function fetchAllBySystem($systemId = 0, $activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT t.*, s.label as system_label, s.code as system_code";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system as s ON t.fk_system = s.rowid";
|
||||
$sql .= " WHERE 1 = 1";
|
||||
if ($systemId > 0) {
|
||||
$sql .= " AND t.fk_system = ".((int) $systemId);
|
||||
}
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND t.active = 1";
|
||||
}
|
||||
$sql .= " ORDER BY t.fk_system ASC, t.position ASC, t.label ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$type = new EquipmentType($this->db);
|
||||
$type->id = $obj->rowid;
|
||||
$type->ref = $obj->ref;
|
||||
$type->label = $obj->label;
|
||||
$type->label_short = $obj->label_short;
|
||||
$type->fk_system = $obj->fk_system;
|
||||
$type->width_te = $obj->width_te;
|
||||
$type->color = $obj->color;
|
||||
$type->fk_product = $obj->fk_product;
|
||||
$type->picto = $obj->picto;
|
||||
$type->is_system = $obj->is_system;
|
||||
$type->position = $obj->position;
|
||||
$type->active = $obj->active;
|
||||
$type->system_label = $obj->system_label;
|
||||
$type->system_code = $obj->system_code;
|
||||
|
||||
$results[] = $type;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch fields for this equipment type
|
||||
*
|
||||
* @param int $activeOnly Only active fields
|
||||
* @return array Array of field objects
|
||||
*/
|
||||
public function fetchFields($activeOnly = 1)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field";
|
||||
$sql .= " WHERE fk_equipment_type = ".((int) $this->id);
|
||||
if ($activeOnly) {
|
||||
$sql .= " AND active = 1";
|
||||
}
|
||||
$sql .= " ORDER BY position ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$results[] = $obj;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
$this->fields = $results;
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fields that should be shown on the SVG block
|
||||
*
|
||||
* @return array Array of field objects with show_on_block = 1
|
||||
*/
|
||||
public function getBlockFields()
|
||||
{
|
||||
$results = array();
|
||||
|
||||
$sql = "SELECT * FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field";
|
||||
$sql .= " WHERE fk_equipment_type = ".((int) $this->id);
|
||||
$sql .= " AND show_on_block = 1";
|
||||
$sql .= " AND active = 1";
|
||||
$sql .= " ORDER BY position ASC";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if ($resql) {
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$results[] = $obj;
|
||||
}
|
||||
$this->db->free($resql);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
|
@ -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'
|
||||
|
||||
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
||||
$this->version = '2.5';
|
||||
$this->version = '3.0';
|
||||
// Url to the file with your last numberversion of this module
|
||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||
|
||||
|
|
@ -393,6 +393,23 @@ class modKundenKarte extends DolibarrModules
|
|||
'target' => '',
|
||||
'user' => 0,
|
||||
);
|
||||
|
||||
// Admin submenu: Manage Equipment Types
|
||||
$this->menu[$r++] = array(
|
||||
'fk_menu' => 'fk_mainmenu=kundenkarte',
|
||||
'type' => 'left',
|
||||
'titre' => 'EquipmentTypes',
|
||||
'prefix' => img_picto('', 'fa-microchip', 'class="pictofixedwidth valignmiddle paddingright"'),
|
||||
'mainmenu' => 'kundenkarte',
|
||||
'leftmenu' => 'kundenkarte_equipment_types',
|
||||
'url' => '/kundenkarte/admin/equipment_types.php',
|
||||
'langs' => 'kundenkarte@kundenkarte',
|
||||
'position' => 1000 + $r,
|
||||
'enabled' => 'isModEnabled("kundenkarte")',
|
||||
'perms' => '$user->hasRight("kundenkarte", "admin")',
|
||||
'target' => '',
|
||||
'user' => 0,
|
||||
);
|
||||
/* END MODULEBUILDER LEFTMENU */
|
||||
|
||||
|
||||
|
|
|
|||
1180
css/kundenkarte.css
1180
css/kundenkarte.css
File diff suppressed because it is too large
Load diff
4329
js/kundenkarte.js
4329
js/kundenkarte.js
File diff suppressed because it is too large
Load diff
|
|
@ -178,6 +178,83 @@ ConfigHelpSystems = Systeme verwalten: Gehen Sie zum Tab "Anlagen-Systeme" um ei
|
|||
ConfigHelpTypes = Element-Typen verwalten: Gehen Sie zum Tab "Element-Typen" um Geraetetypen und Felder zu definieren
|
||||
SetupSaved = Einstellungen gespeichert
|
||||
|
||||
# Equipment (Hutschienen-Komponenten)
|
||||
EquipmentTypes = Equipment-Typen
|
||||
AddEquipmentType = Equipment-Typ hinzufuegen
|
||||
EquipmentTypeFields = Equipment-Felder
|
||||
CanHaveEquipment = Kann Equipment haben
|
||||
CanHaveEquipmentHelp = Hutschienen-Komponenten koennen unter diesem Typ platziert werden
|
||||
WidthTE = Breite (TE)
|
||||
WidthTEHelp = Breite in Teilungseinheiten (1 TE = 18mm)
|
||||
ColorForSVG = Farbe fuer SVG-Darstellung
|
||||
TerminalConfig = Anschlusspunkte
|
||||
TerminalConfigHelp = JSON-Konfiguration der Anschlusspunkte (Terminals)
|
||||
LinkedProduct = Verknuepftes Produkt
|
||||
ShowOnBlock = Auf Block anzeigen
|
||||
ShowInHover = Im Hover anzeigen
|
||||
Carrier = Traeger
|
||||
CarrierLabel = Hutschiene
|
||||
AddCarrier = Traeger hinzufuegen
|
||||
TotalTE = Gesamt TE
|
||||
UsedTE = Belegt
|
||||
FreeTE = Frei
|
||||
Equipment = Equipment
|
||||
AddEquipment = Equipment hinzufuegen
|
||||
DuplicateEquipment = Equipment kopieren
|
||||
DuplicatePrevious = Vorherigen Automaten kopieren
|
||||
DuplicatePreviousCarrier = Vorherige Hutschiene kopieren
|
||||
DuplicatePreviousPanel = Vorheriges Feld kopieren
|
||||
NoSpaceOnCarrier = Kein Platz mehr auf dem Traeger
|
||||
PositionTE = Position (TE)
|
||||
Panels = Felder
|
||||
Fields = Felder
|
||||
AddPanel = Feld hinzufuegen
|
||||
PanelLabel = Feld
|
||||
NoCarriers = Keine Hutschienen
|
||||
DirectCarriers = Direkte Hutschienen
|
||||
NoPanelsOrCarriers = Keine Felder oder Hutschienen vorhanden
|
||||
AddPanelOrCarrier = Feld oder Hutschiene hinzufuegen
|
||||
Protection = Schutzeinrichtung
|
||||
ProtectionLabel = Schutzbezeichnung
|
||||
AssignedToProtection = Gehoert zu Schutzeinrichtung
|
||||
Characteristic = Charakteristik
|
||||
Ampere = Nennstrom
|
||||
Pole = Polzahl
|
||||
Circuit = Stromkreis
|
||||
|
||||
# Connections (Verbindungen - generisch fuer alle Systeme)
|
||||
Connections = Verbindungen
|
||||
Connection = Verbindung
|
||||
AddConnection = Verbindung hinzufuegen
|
||||
AddOutput = Abgang hinzufuegen
|
||||
AddRail = Sammelschiene hinzufuegen
|
||||
AddBusbar = Sammelschiene hinzufuegen
|
||||
Busbar = Sammelschiene
|
||||
ConnectionEditor = Verbindungseditor
|
||||
ConnectionType = Verbindungstyp
|
||||
Color = Farbe
|
||||
OutputLabel = Ziel/Endpunkt
|
||||
MediumType = Medientyp
|
||||
MediumSpec = Spezifikation
|
||||
MediumLength = Laenge
|
||||
SourceEquipment = Von Equipment
|
||||
TargetEquipment = Zu Equipment
|
||||
SourceTerminal = Ausgang von
|
||||
TargetTerminal = Eingang zu
|
||||
InputTerminal = Eingang
|
||||
OutputTerminal = Ausgang
|
||||
RailStart = Schiene von TE
|
||||
RailEnd = Schiene bis TE
|
||||
NoConnections = Keine Verbindungen
|
||||
DeleteConnection = Verbindung loeschen
|
||||
ConfirmDeleteConnection = Moechten Sie diese Verbindung wirklich loeschen?
|
||||
ExternalInput = Externe Einspeisung
|
||||
|
||||
# Beispiel-Verbindungstypen (flexibel, Benutzer kann eigene anlegen)
|
||||
# Strom: L1, L2, L3, N, PE, L1N, 3P, 3P+N, 3P+N+PE
|
||||
# Netzwerk: CAT5, CAT6, CAT7, LWL, Koax
|
||||
# Sicherheit: 2-Draht, 4-Draht, BUS
|
||||
|
||||
# PDF Export
|
||||
PDFExportTemplate = PDF Export Vorlage
|
||||
PDFFontSettings = PDF Schriftgroessen
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ function kundenkarteAdminPrepareHead()
|
|||
$head[$h][2] = 'types';
|
||||
$h++;
|
||||
|
||||
$head[$h][0] = dol_buildpath("/kundenkarte/admin/equipment_types.php", 1);
|
||||
$head[$h][1] = $langs->trans("EquipmentTypes");
|
||||
$head[$h][2] = 'equipment_types';
|
||||
$h++;
|
||||
|
||||
/*
|
||||
$head[$h][0] = dol_buildpath("/kundenkarte/admin/myobject_extrafields.php", 1);
|
||||
$head[$h][1] = $langs->trans("ExtraFields");
|
||||
|
|
|
|||
10
sql/llx_kundenkarte_equipment.key.sql
Normal file
10
sql/llx_kundenkarte_equipment.key.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment ADD INDEX idx_kundenkarte_equipment_carrier (fk_carrier);
|
||||
ALTER TABLE llx_kundenkarte_equipment ADD INDEX idx_kundenkarte_equipment_type (fk_equipment_type);
|
||||
ALTER TABLE llx_kundenkarte_equipment ADD INDEX idx_kundenkarte_equipment_status (status);
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment ADD CONSTRAINT fk_kundenkarte_equipment_carrier FOREIGN KEY (fk_carrier) REFERENCES llx_kundenkarte_equipment_carrier (rowid) ON DELETE CASCADE;
|
||||
ALTER TABLE llx_kundenkarte_equipment ADD CONSTRAINT fk_kundenkarte_equipment_type FOREIGN KEY (fk_equipment_type) REFERENCES llx_kundenkarte_equipment_type (rowid) ON DELETE RESTRICT;
|
||||
36
sql/llx_kundenkarte_equipment.sql
Normal file
36
sql/llx_kundenkarte_equipment.sql
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Table for equipment instances (Sicherungsautomaten, FI-Schalter, etc.)
|
||||
-- Equipment is placed on a carrier (Hutschiene) at a specific position
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment
|
||||
(
|
||||
rowid integer AUTO_INCREMENT PRIMARY KEY,
|
||||
entity integer DEFAULT 1 NOT NULL,
|
||||
|
||||
fk_carrier integer NOT NULL COMMENT 'Traeger/Hutschiene',
|
||||
fk_equipment_type integer NOT NULL COMMENT 'Equipment-Typ',
|
||||
|
||||
label varchar(255) COMMENT 'Optionale Beschriftung/Stromkreis',
|
||||
|
||||
-- Positionierung auf dem Traeger
|
||||
position_te integer NOT NULL COMMENT 'Startposition in TE (0-basiert)',
|
||||
width_te integer NOT NULL COMMENT 'Breite in TE (vom Typ oder ueberschrieben)',
|
||||
|
||||
-- Flexible Felder (JSON)
|
||||
field_values text,
|
||||
|
||||
-- Optionale Produkt-Verknuepfung (ueberschreibt Typ-Produkt)
|
||||
fk_product integer DEFAULT NULL COMMENT 'Spezifisches Dolibarr-Produkt',
|
||||
|
||||
note_private text,
|
||||
status tinyint DEFAULT 1 NOT NULL,
|
||||
|
||||
date_creation datetime,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat integer,
|
||||
fk_user_modif integer,
|
||||
import_key varchar(14)
|
||||
) ENGINE=innodb;
|
||||
8
sql/llx_kundenkarte_equipment_carrier.key.sql
Normal file
8
sql/llx_kundenkarte_equipment_carrier.key.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_carrier ADD INDEX idx_kundenkarte_carrier_anlage (fk_anlage);
|
||||
ALTER TABLE llx_kundenkarte_equipment_carrier ADD INDEX idx_kundenkarte_carrier_status (status);
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_carrier ADD CONSTRAINT fk_kundenkarte_carrier_anlage FOREIGN KEY (fk_anlage) REFERENCES llx_kundenkarte_anlage (rowid) ON DELETE CASCADE;
|
||||
26
sql/llx_kundenkarte_equipment_carrier.sql
Normal file
26
sql/llx_kundenkarte_equipment_carrier.sql
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Table for equipment carriers (Hutschienen/Traeger)
|
||||
-- A carrier belongs to a technical place (Anlage) and has a capacity in TE
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment_carrier
|
||||
(
|
||||
rowid integer AUTO_INCREMENT PRIMARY KEY,
|
||||
entity integer DEFAULT 1 NOT NULL,
|
||||
|
||||
fk_anlage integer NOT NULL COMMENT 'Technischer Platz (z.B. Unterverteiler, Zaehlerschrank)',
|
||||
label varchar(255) NOT NULL COMMENT 'Bezeichnung (z.B. Hutschiene 1, Obere Reihe)',
|
||||
|
||||
total_te integer DEFAULT 12 NOT NULL COMMENT 'Gesamtkapazitaet in Teilungseinheiten',
|
||||
position integer DEFAULT 0 COMMENT 'Reihenfolge der Traeger',
|
||||
|
||||
note_private text,
|
||||
status tinyint DEFAULT 1 NOT NULL,
|
||||
|
||||
date_creation datetime,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat integer,
|
||||
fk_user_modif integer
|
||||
) ENGINE=innodb;
|
||||
5
sql/llx_kundenkarte_equipment_connection.key.sql
Normal file
5
sql/llx_kundenkarte_equipment_connection.key.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
-- Update script for equipment_connection table - adds rail_phases and excluded_te
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD COLUMN IF NOT EXISTS rail_phases VARCHAR(20) DEFAULT NULL;
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD COLUMN IF NOT EXISTS excluded_te VARCHAR(100) DEFAULT NULL;
|
||||
61
sql/llx_kundenkarte_equipment_connection.sql
Normal file
61
sql/llx_kundenkarte_equipment_connection.sql
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Equipment connections (Verbindungen zwischen Equipment)
|
||||
-- Generic connection system for any installation type (electrical, network, security, etc.)
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment_connection (
|
||||
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
entity INTEGER DEFAULT 1 NOT NULL,
|
||||
|
||||
-- Source equipment (where connection comes FROM)
|
||||
fk_source INTEGER, -- NULL = external input
|
||||
source_terminal VARCHAR(20) DEFAULT 'output', -- Terminal identifier (flexible)
|
||||
|
||||
-- Target equipment (where connection goes TO)
|
||||
fk_target INTEGER, -- NULL = output/endpoint
|
||||
target_terminal VARCHAR(20) DEFAULT 'input', -- Terminal identifier (flexible)
|
||||
|
||||
-- Connection properties (flexible, user-defined)
|
||||
connection_type VARCHAR(50), -- User-defined type (e.g., "L1N", "CAT6", "2-Draht", etc.)
|
||||
color VARCHAR(20), -- Display color (hex code)
|
||||
|
||||
-- Output/endpoint info (when fk_target is NULL)
|
||||
output_label VARCHAR(255), -- e.g., "Küche Steckdosen", "Büro PC1", "Haustür"
|
||||
|
||||
-- Medium info (cable, wire, etc.) - all flexible text fields
|
||||
medium_type VARCHAR(100), -- e.g., "NYM-J", "CAT6 S/FTP", "2x0.8 J-Y(St)Y"
|
||||
medium_spec VARCHAR(100), -- e.g., "3x2.5", "AWG23", "Ring 1"
|
||||
medium_length VARCHAR(50), -- Length as text (allows "ca. 15m", "5-10m", etc.)
|
||||
|
||||
-- Rail/bar connections (spans multiple equipment)
|
||||
is_rail TINYINT DEFAULT 0, -- 1 = this is a rail/bar spanning multiple slots
|
||||
rail_start_te INTEGER, -- Start position on carrier
|
||||
rail_end_te INTEGER, -- End position on carrier
|
||||
rail_phases VARCHAR(20), -- '3P', '3P+N', 'L1', 'L1N', etc. for multi-line display
|
||||
excluded_te VARCHAR(100), -- Comma-separated TE positions to exclude (gaps for FI)
|
||||
|
||||
fk_carrier INTEGER, -- Carrier where this connection is rendered
|
||||
position_y INTEGER DEFAULT 0, -- Y offset for rendering (0=first row, 1=second row, etc.)
|
||||
|
||||
note_private TEXT,
|
||||
status INTEGER DEFAULT 1,
|
||||
|
||||
date_creation DATETIME,
|
||||
tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat INTEGER,
|
||||
fk_user_modif INTEGER
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- Indexes
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD INDEX idx_connection_source (fk_source);
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD INDEX idx_connection_target (fk_target);
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD INDEX idx_connection_carrier (fk_carrier);
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD INDEX idx_connection_entity (entity);
|
||||
|
||||
-- Foreign keys
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD CONSTRAINT fk_connection_source
|
||||
FOREIGN KEY (fk_source) REFERENCES llx_kundenkarte_equipment(rowid) ON DELETE CASCADE;
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD CONSTRAINT fk_connection_target
|
||||
FOREIGN KEY (fk_target) REFERENCES llx_kundenkarte_equipment(rowid) ON DELETE CASCADE;
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection ADD CONSTRAINT fk_connection_carrier
|
||||
FOREIGN KEY (fk_carrier) REFERENCES llx_kundenkarte_equipment_carrier(rowid) ON DELETE CASCADE;
|
||||
28
sql/llx_kundenkarte_equipment_panel.sql
Normal file
28
sql/llx_kundenkarte_equipment_panel.sql
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Equipment Panel table (Schaltschrankfelder)
|
||||
-- Represents physical sections/fields in a distribution board
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment_panel (
|
||||
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
entity INTEGER DEFAULT 1 NOT NULL,
|
||||
|
||||
fk_anlage INTEGER NOT NULL, -- Zählerschrank/UV that contains this panel
|
||||
label VARCHAR(128), -- "Feld 1", "Linkes Feld", etc.
|
||||
position INTEGER DEFAULT 0, -- Order (left to right)
|
||||
|
||||
note_private TEXT,
|
||||
status SMALLINT DEFAULT 1, -- 1=active, 0=inactive
|
||||
|
||||
date_creation DATETIME,
|
||||
tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat INTEGER,
|
||||
fk_user_modif INTEGER,
|
||||
import_key VARCHAR(14),
|
||||
|
||||
INDEX idx_panel_anlage (fk_anlage),
|
||||
CONSTRAINT fk_panel_anlage FOREIGN KEY (fk_anlage)
|
||||
REFERENCES llx_kundenkarte_anlage(rowid) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
10
sql/llx_kundenkarte_equipment_type.key.sql
Normal file
10
sql/llx_kundenkarte_equipment_type.key.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_type ADD UNIQUE INDEX uk_kundenkarte_equipment_type_ref (ref, entity);
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_type ADD INDEX idx_kundenkarte_equipment_type_fk_system (fk_system);
|
||||
ALTER TABLE llx_kundenkarte_equipment_type ADD INDEX idx_kundenkarte_equipment_type_active (active);
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_type ADD CONSTRAINT fk_kundenkarte_equipment_type_fk_system FOREIGN KEY (fk_system) REFERENCES llx_c_kundenkarte_anlage_system (rowid);
|
||||
38
sql/llx_kundenkarte_equipment_type.sql
Normal file
38
sql/llx_kundenkarte_equipment_type.sql
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Table for equipment type templates (Hutschienen-Komponenten)
|
||||
-- Examples: Leitungsschutzschalter, FI-Schalter, Hauptschalter, etc.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment_type
|
||||
(
|
||||
rowid integer AUTO_INCREMENT PRIMARY KEY,
|
||||
entity integer DEFAULT 0 NOT NULL,
|
||||
|
||||
ref varchar(64) NOT NULL,
|
||||
label varchar(255) NOT NULL,
|
||||
label_short varchar(32),
|
||||
description text,
|
||||
|
||||
fk_system integer NOT NULL,
|
||||
|
||||
-- Equipment-spezifische Felder
|
||||
width_te integer DEFAULT 1 NOT NULL COMMENT 'Standardbreite in Teilungseinheiten (TE)',
|
||||
color varchar(8) COMMENT 'Farbcode fuer SVG-Darstellung (z.B. #3498db)',
|
||||
|
||||
-- Optionale Produkt-Verknuepfung
|
||||
fk_product integer DEFAULT NULL COMMENT 'Optionales Standard-Dolibarr-Produkt',
|
||||
|
||||
picto varchar(64),
|
||||
is_system tinyint DEFAULT 0 NOT NULL,
|
||||
|
||||
position integer DEFAULT 0,
|
||||
active tinyint DEFAULT 1 NOT NULL,
|
||||
|
||||
date_creation datetime,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat integer,
|
||||
fk_user_modif integer,
|
||||
import_key varchar(14)
|
||||
) ENGINE=innodb;
|
||||
8
sql/llx_kundenkarte_equipment_type_field.key.sql
Normal file
8
sql/llx_kundenkarte_equipment_type_field.key.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_type_field ADD INDEX idx_kundenkarte_equip_type_field_type (fk_equipment_type);
|
||||
ALTER TABLE llx_kundenkarte_equipment_type_field ADD INDEX idx_kundenkarte_equip_type_field_active (active);
|
||||
|
||||
ALTER TABLE llx_kundenkarte_equipment_type_field ADD CONSTRAINT fk_kundenkarte_equip_type_field_type FOREIGN KEY (fk_equipment_type) REFERENCES llx_kundenkarte_equipment_type (rowid) ON DELETE CASCADE;
|
||||
33
sql/llx_kundenkarte_equipment_type_field.sql
Normal file
33
sql/llx_kundenkarte_equipment_type_field.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Table for defining fields per equipment type (EAV pattern for flexibility)
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE llx_kundenkarte_equipment_type_field
|
||||
(
|
||||
rowid integer AUTO_INCREMENT PRIMARY KEY,
|
||||
entity integer DEFAULT 0 NOT NULL,
|
||||
|
||||
fk_equipment_type integer NOT NULL,
|
||||
|
||||
field_code varchar(64) NOT NULL,
|
||||
field_label varchar(255) NOT NULL,
|
||||
field_type varchar(32) NOT NULL,
|
||||
field_options text,
|
||||
|
||||
field_size integer DEFAULT 255,
|
||||
field_default varchar(255),
|
||||
|
||||
required tinyint DEFAULT 0 NOT NULL,
|
||||
show_in_hover tinyint DEFAULT 1 NOT NULL,
|
||||
show_on_block tinyint DEFAULT 0 NOT NULL COMMENT 'Auf der SVG-Darstellung anzeigen',
|
||||
|
||||
position integer DEFAULT 0,
|
||||
active tinyint DEFAULT 1 NOT NULL,
|
||||
|
||||
date_creation datetime,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat integer,
|
||||
fk_user_modif integer
|
||||
) ENGINE=innodb;
|
||||
12
sql/update_3.0.0.sql
Normal file
12
sql/update_3.0.0.sql
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Update script for version 3.0.0
|
||||
-- Adds can_have_equipment column to anlage_type table
|
||||
-- ============================================================================
|
||||
|
||||
-- Add can_have_equipment to existing anlage_type table
|
||||
ALTER TABLE llx_kundenkarte_anlage_type
|
||||
ADD COLUMN can_have_equipment tinyint DEFAULT 0 NOT NULL
|
||||
COMMENT 'Ob dieser Typ Equipment (Hutschienen-Komponenten) haben kann'
|
||||
AFTER allowed_parent_types;
|
||||
41
sql/update_3.1.0.sql
Normal file
41
sql/update_3.1.0.sql
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
-- ============================================================================
|
||||
-- Copyright (C) 2026 Alles Watt lauft
|
||||
--
|
||||
-- Update script for version 3.1.0
|
||||
-- Adds panels (Schaltschrankfelder) and FI protection assignment
|
||||
-- ============================================================================
|
||||
|
||||
-- 1. Create equipment_panel table
|
||||
CREATE TABLE IF NOT EXISTS llx_kundenkarte_equipment_panel (
|
||||
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
entity INTEGER DEFAULT 1 NOT NULL,
|
||||
fk_anlage INTEGER NOT NULL,
|
||||
label VARCHAR(128),
|
||||
position INTEGER DEFAULT 0,
|
||||
note_private TEXT,
|
||||
status SMALLINT DEFAULT 1,
|
||||
date_creation DATETIME,
|
||||
tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
fk_user_creat INTEGER,
|
||||
fk_user_modif INTEGER,
|
||||
import_key VARCHAR(14),
|
||||
INDEX idx_panel_anlage (fk_anlage)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- 2. Add fk_panel to equipment_carrier (optional - carrier can belong to panel or directly to anlage)
|
||||
ALTER TABLE llx_kundenkarte_equipment_carrier
|
||||
ADD COLUMN fk_panel INTEGER DEFAULT NULL AFTER fk_anlage,
|
||||
ADD INDEX idx_carrier_panel (fk_panel);
|
||||
|
||||
-- 3. Add fk_protection to equipment (for FI/RCD assignment)
|
||||
ALTER TABLE llx_kundenkarte_equipment
|
||||
ADD COLUMN fk_protection INTEGER DEFAULT NULL
|
||||
COMMENT 'FK to protection device (FI/RCD) that protects this equipment'
|
||||
AFTER fk_product,
|
||||
ADD INDEX idx_equipment_protection (fk_protection);
|
||||
|
||||
-- 4. Add protection_label field to show above protected equipment
|
||||
ALTER TABLE llx_kundenkarte_equipment
|
||||
ADD COLUMN protection_label VARCHAR(64) DEFAULT NULL
|
||||
COMMENT 'Label shown above equipment when part of protection group'
|
||||
AFTER fk_protection;
|
||||
78
sql/update_3.2.0.sql
Normal file
78
sql/update_3.2.0.sql
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
-- ============================================================================
|
||||
-- KundenKarte Module Update 3.2.0
|
||||
-- Add terminals configuration for equipment types
|
||||
-- ============================================================================
|
||||
|
||||
-- Add terminals_config field to equipment_type table
|
||||
-- JSON format for defining input/output terminals
|
||||
-- Example: {"inputs": [{"id": "in_L", "label": "L"}, {"id": "in_N", "label": "N"}], "outputs": [{"id": "out_L", "label": "L"}, {"id": "out_N", "label": "N"}]}
|
||||
ALTER TABLE llx_kundenkarte_equipment_type
|
||||
ADD COLUMN terminals_config TEXT DEFAULT NULL COMMENT 'JSON config for terminals (inputs/outputs)';
|
||||
|
||||
-- Add free position fields for equipment in the schematic editor
|
||||
ALTER TABLE llx_kundenkarte_equipment
|
||||
ADD COLUMN editor_x INTEGER DEFAULT NULL COMMENT 'X position in schematic editor',
|
||||
ADD COLUMN editor_y INTEGER DEFAULT NULL COMMENT 'Y position in schematic editor';
|
||||
|
||||
-- Update connection table to support terminal-based connections
|
||||
ALTER TABLE llx_kundenkarte_equipment_connection
|
||||
ADD COLUMN source_terminal_id VARCHAR(64) DEFAULT NULL COMMENT 'Source terminal ID (e.g., out_L, out_N)',
|
||||
ADD COLUMN target_terminal_id VARCHAR(64) DEFAULT NULL COMMENT 'Target terminal ID (e.g., in_L, in_N)';
|
||||
|
||||
-- Default terminal configurations for common equipment types
|
||||
-- These can be customized by the user
|
||||
|
||||
-- LS (Leitungsschutzschalter) - 1 input, 1 output
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in","label":"●","pos":"top"}],"outputs":[{"id":"out","label":"●","pos":"bottom"}]}'
|
||||
WHERE ref IN ('LS', 'LSS', 'B16', 'C16') AND terminals_config IS NULL;
|
||||
|
||||
-- FI (Fehlerstromschutzschalter) - 2 inputs, 2 outputs (L+N)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L","label":"L","pos":"top-left"},{"id":"in_N","label":"N","pos":"top-right"}],"outputs":[{"id":"out_L","label":"L","pos":"bottom-left"},{"id":"out_N","label":"N","pos":"bottom-right"}]}'
|
||||
WHERE ref IN ('FI', 'RCD', 'RCCB') AND terminals_config IS NULL;
|
||||
|
||||
-- FI/LS Kombi - 2 inputs, 2 outputs
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L","label":"L","pos":"top-left"},{"id":"in_N","label":"N","pos":"top-right"}],"outputs":[{"id":"out_L","label":"L","pos":"bottom-left"},{"id":"out_N","label":"N","pos":"bottom-right"}]}'
|
||||
WHERE ref IN ('FILS', 'RCBO') AND terminals_config IS NULL;
|
||||
|
||||
-- 3-poliger LS - 3 inputs, 3 outputs
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L1","label":"L1","pos":"top"},{"id":"in_L2","label":"L2","pos":"top"},{"id":"in_L3","label":"L3","pos":"top"}],"outputs":[{"id":"out_L1","label":"L1","pos":"bottom"},{"id":"out_L2","label":"L2","pos":"bottom"},{"id":"out_L3","label":"L3","pos":"bottom"}]}'
|
||||
WHERE ref IN ('LS3P', 'C3P') AND terminals_config IS NULL;
|
||||
|
||||
-- 4-poliger FI - 4 inputs, 4 outputs
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L1","label":"L1","pos":"top"},{"id":"in_L2","label":"L2","pos":"top"},{"id":"in_L3","label":"L3","pos":"top"},{"id":"in_N","label":"N","pos":"top"}],"outputs":[{"id":"out_L1","label":"L1","pos":"bottom"},{"id":"out_L2","label":"L2","pos":"bottom"},{"id":"out_L3","label":"L3","pos":"bottom"},{"id":"out_N","label":"N","pos":"bottom"}]}'
|
||||
WHERE ref IN ('FI4P', 'RCD4P') AND terminals_config IS NULL;
|
||||
|
||||
-- Hauptschalter - variable (default 3P+N)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L1","label":"L1","pos":"top"},{"id":"in_L2","label":"L2","pos":"top"},{"id":"in_L3","label":"L3","pos":"top"},{"id":"in_N","label":"N","pos":"top"}],"outputs":[{"id":"out_L1","label":"L1","pos":"bottom"},{"id":"out_L2","label":"L2","pos":"bottom"},{"id":"out_L3","label":"L3","pos":"bottom"},{"id":"out_N","label":"N","pos":"bottom"}]}'
|
||||
WHERE ref IN ('HS', 'HAUPTSCHALTER') AND terminals_config IS NULL;
|
||||
|
||||
-- Schütz/Relais - 2 inputs, 2 outputs (Steuerstromkreis + Lastkreis)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_A1","label":"A1","pos":"top-left"},{"id":"in_1","label":"1","pos":"top-right"}],"outputs":[{"id":"out_A2","label":"A2","pos":"bottom-left"},{"id":"out_2","label":"2","pos":"bottom-right"}]}'
|
||||
WHERE ref IN ('SCHUETZ', 'RELAIS', 'K') AND terminals_config IS NULL;
|
||||
|
||||
-- Stromstoßschalter - Steuerung + 2 Lastanschlüsse
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_A1","label":"A1","pos":"top-left"},{"id":"in_1","label":"1","pos":"top-right"}],"outputs":[{"id":"out_A2","label":"A2","pos":"bottom-left"},{"id":"out_2","label":"2","pos":"bottom-right"}]}'
|
||||
WHERE ref IN ('SSS', 'STROMSTOSS') AND terminals_config IS NULL;
|
||||
|
||||
-- Klemme - durchgehend
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in","label":"●","pos":"top"}],"outputs":[{"id":"out","label":"●","pos":"bottom"}]}'
|
||||
WHERE ref IN ('KLEMME', 'REIHENKLEMME', 'RK') AND terminals_config IS NULL;
|
||||
|
||||
-- Überspannungsschutz - 3P+N+PE
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in_L1","label":"L1","pos":"top"},{"id":"in_L2","label":"L2","pos":"top"},{"id":"in_L3","label":"L3","pos":"top"},{"id":"in_N","label":"N","pos":"top"}],"outputs":[{"id":"out_PE","label":"PE","pos":"bottom"}]}'
|
||||
WHERE ref IN ('SPD', 'UESP') AND terminals_config IS NULL;
|
||||
|
||||
-- Default for any equipment without config: 1 input, 1 output
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"inputs":[{"id":"in","label":"●","pos":"top"}],"outputs":[{"id":"out","label":"●","pos":"bottom"}]}'
|
||||
WHERE terminals_config IS NULL;
|
||||
54
sql/update_3.3.0.sql
Normal file
54
sql/update_3.3.0.sql
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
-- ============================================================================
|
||||
-- KundenKarte Module Update 3.3.0
|
||||
-- Correct terminal configurations (bidirectional format)
|
||||
-- ============================================================================
|
||||
|
||||
-- FI (Fehlerstromschutzschalter) - 4 Terminals (2 oben: L+N, 2 unten: L+N)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L","pos":"top"},{"id":"t2","label":"N","pos":"top"},{"id":"t3","label":"L","pos":"bottom"},{"id":"t4","label":"N","pos":"bottom"}]}'
|
||||
WHERE ref IN ('FI', 'RCD', 'RCCB');
|
||||
|
||||
-- FI/LS Kombi - 4 Terminals
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L","pos":"top"},{"id":"t2","label":"N","pos":"top"},{"id":"t3","label":"L","pos":"bottom"},{"id":"t4","label":"N","pos":"bottom"}]}'
|
||||
WHERE ref IN ('FILS', 'RCBO');
|
||||
|
||||
-- HS (Hauptschalter) - 3 Pole (L1, L2, L3) ohne N
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"L1","pos":"bottom"},{"id":"t5","label":"L2","pos":"bottom"},{"id":"t6","label":"L3","pos":"bottom"}]}'
|
||||
WHERE ref IN ('HS', 'HAUPTSCHALTER');
|
||||
|
||||
-- LS (Leitungsschutzschalter) - 2 Terminals (1 oben, 1 unten)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"●","pos":"top"},{"id":"t2","label":"●","pos":"bottom"}]}'
|
||||
WHERE ref IN ('LS', 'LSS', 'B16', 'C16') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- 3-poliger LS - 6 Terminals
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"L1","pos":"bottom"},{"id":"t5","label":"L2","pos":"bottom"},{"id":"t6","label":"L3","pos":"bottom"}]}'
|
||||
WHERE ref IN ('LS3P', 'C3P') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- 4-poliger FI - 8 Terminals (3P+N)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"N","pos":"top"},{"id":"t5","label":"L1","pos":"bottom"},{"id":"t6","label":"L2","pos":"bottom"},{"id":"t7","label":"L3","pos":"bottom"},{"id":"t8","label":"N","pos":"bottom"}]}'
|
||||
WHERE ref IN ('FI4P', 'RCD4P') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- Schuetz/Relais - 4 Terminals
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"A1","pos":"top"},{"id":"t2","label":"1","pos":"top"},{"id":"t3","label":"A2","pos":"bottom"},{"id":"t4","label":"2","pos":"bottom"}]}'
|
||||
WHERE ref IN ('SCHUETZ', 'RELAIS', 'K') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- Klemme - 2 Terminals
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"●","pos":"top"},{"id":"t2","label":"●","pos":"bottom"}]}'
|
||||
WHERE ref IN ('KLEMME', 'REIHENKLEMME', 'RK') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- Ueberspannungsschutz - 5 Terminals (3P+N oben, PE unten)
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"L1","pos":"top"},{"id":"t2","label":"L2","pos":"top"},{"id":"t3","label":"L3","pos":"top"},{"id":"t4","label":"N","pos":"top"},{"id":"t5","label":"PE","pos":"bottom"}]}'
|
||||
WHERE ref IN ('SPD', 'UESP') AND (terminals_config IS NULL OR terminals_config LIKE '%inputs%');
|
||||
|
||||
-- Default: 2 Terminals fuer alle ohne Konfiguration
|
||||
UPDATE llx_kundenkarte_equipment_type
|
||||
SET terminals_config = '{"terminals":[{"id":"t1","label":"●","pos":"top"},{"id":"t2","label":"●","pos":"bottom"}]}'
|
||||
WHERE terminals_config IS NULL OR terminals_config = '';
|
||||
1419
tabs/anlagen.php
1419
tabs/anlagen.php
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue