Neue Features: - Phasenschienen-Typen Admin-Seite (Sammelschienen konfigurierbar) - 12 vordefinierte Phasenschienen-Typen (L1, L2, L3, N, PE, 3P, 3P+N etc.) - Block-Bilder fuer Equipment-Typen (individuelle Darstellung) - Reihenklemmen mit gestapelten Terminals (Mehrstockklemmen) - Bruecken-System zwischen Reihenklemmen - Phasenschienen per Drag & Drop verschiebbar (auch zwischen Hutschienen) - Terminal-Labels mit dunklem Badge-Hintergrund Technische Aenderungen: - Neue Tabelle: llx_kundenkarte_busbar_type (Phasenschienen-Typen) - Neue Tabelle: llx_kundenkarte_terminal_bridge (Klemmen-Bruecken) - Neue PHP-Klassen: BusbarType, TerminalBridge - Equipment-Type block_image Upload - Terminals mit row/col Eigenschaften fuer Stapelung - CSS-Optimierungen fuer Layout-Stabilitaet Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
413 lines
13 KiB
PHP
413 lines
13 KiB
PHP
<?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,
|
|
'type_label_short' => $equipment->type_label_short,
|
|
'type_color' => $equipment->type_color,
|
|
'type_icon_file' => $equipment->type_icon_file,
|
|
'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) {
|
|
$iconUrl = '';
|
|
if (!empty($eq->type_icon_file)) {
|
|
$iconUrl = DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file=equipment_icons/'.urlencode($eq->type_icon_file);
|
|
}
|
|
$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,
|
|
'type_icon_file' => $eq->type_icon_file,
|
|
'type_icon_url' => $iconUrl,
|
|
'type_block_image' => $eq->type_block_image,
|
|
'type_block_image_url' => !empty($eq->type_block_image) ? DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file=block_images/'.urlencode($eq->type_block_image) : '',
|
|
'type_flow_direction' => $eq->type_flow_direction,
|
|
'type_terminal_position' => $eq->type_terminal_position ?: 'both',
|
|
'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 'move_to_carrier':
|
|
// Move equipment to different carrier (drag-drop between carriers)
|
|
if (!$user->hasRight('kundenkarte', 'write')) {
|
|
$response['error'] = 'Permission denied';
|
|
break;
|
|
}
|
|
if ($equipment->fetch($equipmentId) > 0) {
|
|
$newCarrierId = GETPOSTINT('carrier_id');
|
|
$newPosition = GETPOSTINT('position_te') ?: 1;
|
|
|
|
// Check if target carrier exists
|
|
$targetCarrier = new EquipmentCarrier($db);
|
|
if ($targetCarrier->fetch($newCarrierId) <= 0) {
|
|
$response['error'] = 'Target carrier not found';
|
|
break;
|
|
}
|
|
|
|
// Check if position is available on target carrier
|
|
if (!$targetCarrier->isPositionAvailable($newPosition, $equipment->width_te, 0)) {
|
|
$response['error'] = 'Position auf Ziel-Hutschiene nicht verfügbar';
|
|
break;
|
|
}
|
|
|
|
// Update equipment
|
|
$equipment->fk_carrier = $newCarrierId;
|
|
$equipment->position_te = $newPosition;
|
|
$result = $equipment->update($user);
|
|
if ($result > 0) {
|
|
$response['success'] = true;
|
|
$response['message'] = 'Equipment verschoben';
|
|
} 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,
|
|
'fk_carrier' => $newEquipment->fk_carrier,
|
|
'type_id' => $newEquipment->fk_equipment_type,
|
|
'type_label' => $newEquipment->type_label,
|
|
'type_label_short' => $newEquipment->type_label_short,
|
|
'type_color' => $newEquipment->type_color,
|
|
'type_ref' => $newEquipment->type_ref,
|
|
'type_icon_file' => $newEquipment->type_icon_file,
|
|
'terminals_config' => $newEquipment->terminals_config,
|
|
'label' => $newEquipment->label,
|
|
'position_te' => $newEquipment->position_te,
|
|
'width_te' => $newEquipment->width_te,
|
|
'block_label' => $newEquipment->getBlockLabel(),
|
|
'block_color' => $newEquipment->getBlockColor(),
|
|
'field_values' => $newEquipment->getFieldValues(),
|
|
'fk_product' => $newEquipment->fk_product
|
|
);
|
|
}
|
|
} 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();
|