- buildTerminalPhaseMap: Schritt 1b - Leitungen mit expliziter Farbe als Startpunkte (nur Gerät→Gerät, keine Abgänge) - buildTerminalPhaseMap: Block-Durchreichung (Top↔Bottom) entfernt - buildTerminalPhaseMap: Junction-Verbindungen (Terminal→Leitung) bidirektional verarbeitet via _connectionById Index - PWA: Abgangs-Rendering mit Index-Fallback wenn source_terminal_id fehlt - PWA: Abgangs-Labels max-height 130px, min-height 30px - Auto-Naming: EquipmentCarrier create/update → 'R' + count - Auto-Naming: EquipmentPanel update → 'Feld ' + count - pwa_api.php: Hardcoded Fallbacks 'Feld'/'Hutschiene' entfernt - pwa.js: Hutschiene Auto-Naming dynamisch aus Panel-Carrier-Anzahl - kundenkarte.js: Carrier-Dialog Placeholder 'z.B. R1 (automatisch)' - SW Cache auf v12.5 hochgezählt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
306 lines
12 KiB
PHP
Executable file
306 lines
12 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* Edit page for Anlage Connection (cable/wire between elements)
|
|
*/
|
|
|
|
$res = 0;
|
|
if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php";
|
|
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
|
|
if (!$res) die("Include of main fails");
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
|
|
dol_include_once('/kundenkarte/class/anlageconnection.class.php');
|
|
dol_include_once('/kundenkarte/class/anlage.class.php');
|
|
dol_include_once('/kundenkarte/class/mediumtype.class.php');
|
|
|
|
$langs->loadLangs(array('kundenkarte@kundenkarte'));
|
|
|
|
$id = GETPOSTINT('id');
|
|
$socId = GETPOSTINT('socid');
|
|
$contactId = GETPOSTINT('contactid');
|
|
$systemId = GETPOSTINT('system_id');
|
|
$sourceId = GETPOSTINT('source_id');
|
|
$action = GETPOST('action', 'aZ09');
|
|
|
|
// Security check
|
|
if (!$user->hasRight('kundenkarte', 'read')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
$connection = new AnlageConnection($db);
|
|
$anlage = new Anlage($db);
|
|
$form = new Form($db);
|
|
|
|
// Load existing connection
|
|
if ($id > 0) {
|
|
$result = $connection->fetch($id);
|
|
if ($result <= 0) {
|
|
setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors');
|
|
header('Location: '.DOL_URL_ROOT.'/societe/card.php?socid='.$socId);
|
|
exit;
|
|
}
|
|
// Get socId from source anlage if not provided
|
|
if (empty($socId)) {
|
|
$tmpAnlage = new Anlage($db);
|
|
if ($tmpAnlage->fetch($connection->fk_source) > 0) {
|
|
$socId = $tmpAnlage->fk_soc;
|
|
$systemId = $tmpAnlage->fk_system;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Redirect-URL: zurück zur Kontakt- oder Kunden-Anlagenansicht
|
|
if ($contactId > 0) {
|
|
$backUrl = dol_buildpath('/kundenkarte/tabs/contact_anlagen.php', 1).'?id='.$contactId.'&system='.$systemId;
|
|
} else {
|
|
$backUrl = dol_buildpath('/kundenkarte/tabs/anlagen.php', 1).'?id='.$socId.'&system='.$systemId;
|
|
}
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
if ($action == 'update' && $user->hasRight('kundenkarte', 'write')) {
|
|
$connection->fk_source = GETPOSTINT('fk_source');
|
|
$connection->fk_target = GETPOSTINT('fk_target');
|
|
$connection->label = GETPOST('label', 'alphanohtml');
|
|
$connection->fk_medium_type = GETPOSTINT('fk_medium_type');
|
|
$connection->medium_type_text = GETPOST('medium_type_text', 'alphanohtml');
|
|
$connection->medium_spec = GETPOST('medium_spec', 'alphanohtml');
|
|
$connection->medium_length = GETPOST('medium_length', 'alphanohtml');
|
|
$connection->medium_color = GETPOST('medium_color', 'alphanohtml');
|
|
$connection->route_description = GETPOST('route_description', 'restricthtml');
|
|
$connection->installation_date = GETPOST('installation_date', 'alpha');
|
|
|
|
if (empty($connection->fk_source) || empty($connection->fk_target)) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', 'Quelle/Ziel'), null, 'errors');
|
|
} else {
|
|
$result = $connection->update($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$backUrl);
|
|
exit;
|
|
} else {
|
|
setEventMessages($connection->error, null, 'errors');
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($action == 'add' && $user->hasRight('kundenkarte', 'write')) {
|
|
$connection->fk_source = GETPOSTINT('fk_source');
|
|
$connection->fk_target = GETPOSTINT('fk_target');
|
|
$connection->label = GETPOST('label', 'alphanohtml');
|
|
$connection->fk_medium_type = GETPOSTINT('fk_medium_type');
|
|
$connection->medium_type_text = GETPOST('medium_type_text', 'alphanohtml');
|
|
$connection->medium_spec = GETPOST('medium_spec', 'alphanohtml');
|
|
$connection->medium_length = GETPOST('medium_length', 'alphanohtml');
|
|
$connection->medium_color = GETPOST('medium_color', 'alphanohtml');
|
|
$connection->route_description = GETPOST('route_description', 'restricthtml');
|
|
$connection->installation_date = GETPOST('installation_date', 'alpha');
|
|
$connection->status = 1;
|
|
|
|
if (empty($connection->fk_source) || empty($connection->fk_target)) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', 'Quelle/Ziel'), null, 'errors');
|
|
} else {
|
|
$result = $connection->create($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$backUrl);
|
|
exit;
|
|
} else {
|
|
setEventMessages($connection->error, null, 'errors');
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($action == 'delete' && $user->hasRight('kundenkarte', 'write')) {
|
|
$result = $connection->delete($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
|
header('Location: '.$backUrl);
|
|
exit;
|
|
} else {
|
|
setEventMessages($connection->error, null, 'errors');
|
|
}
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$title = $id > 0 ? 'Verbindung bearbeiten' : 'Neue Verbindung';
|
|
llxHeader('', $title);
|
|
|
|
// Gebäude-Typ-IDs ermitteln (Verbindungen nur zwischen Geräten, nicht Gebäuden)
|
|
$buildingTypeIds = array();
|
|
$sqlBt = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."kundenkarte_anlage_type t";
|
|
$sqlBt .= " LEFT JOIN ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system ts ON t.fk_system = ts.rowid";
|
|
$sqlBt .= " WHERE ts.code = 'GLOBAL'";
|
|
$resBt = $db->query($sqlBt);
|
|
if ($resBt) {
|
|
while ($btObj = $db->fetch_object($resBt)) {
|
|
$buildingTypeIds[] = (int) $btObj->rowid;
|
|
}
|
|
}
|
|
|
|
// Alle Elemente für Dropdowns laden (OHNE System-Filter, da Kabel systemübergreifend sein können)
|
|
$anlagenList = array();
|
|
if ($socId > 0) {
|
|
if ($contactId > 0) {
|
|
$tree = $anlage->fetchTreeByContact($socId, $contactId, 0);
|
|
} else {
|
|
$tree = $anlage->fetchTree($socId, 0);
|
|
}
|
|
// Baum flach machen - nur Geräte, Gebäude als Pfad-Kontext
|
|
$flattenTree = function($nodes, $path = '') use (&$flattenTree, &$anlagenList, &$buildingTypeIds) {
|
|
foreach ($nodes as $node) {
|
|
$isBuilding = in_array((int) $node->fk_anlage_type, $buildingTypeIds);
|
|
|
|
if ($isBuilding) {
|
|
// Gebäude/Raum: nicht wählbar, aber Pfad als Kontext weitergeben
|
|
$newPath = $path ? $path.' > '.$node->label : $node->label;
|
|
if (!empty($node->children)) {
|
|
$flattenTree($node->children, $newPath);
|
|
}
|
|
} else {
|
|
// Gerät: in Liste aufnehmen mit Gebäude-Pfad als Kontext
|
|
$typeInfo = !empty($node->type_short) ? $node->type_short : (!empty($node->type_label) ? $node->type_label : '');
|
|
$label = '';
|
|
if (!empty($path)) {
|
|
$label = $path.' > ';
|
|
}
|
|
$label .= $node->label;
|
|
if (!empty($typeInfo)) {
|
|
$label .= ' ['.$typeInfo.']';
|
|
}
|
|
$anlagenList[$node->id] = array(
|
|
'label' => $label,
|
|
'picto' => !empty($node->type_picto) ? $node->type_picto : 'fa-cube',
|
|
);
|
|
// Rekursion in Geräte-Kinder
|
|
if (!empty($node->children)) {
|
|
$flattenTree($node->children, $path);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
$flattenTree($tree);
|
|
}
|
|
|
|
// Load medium types
|
|
$mediumTypes = array();
|
|
$sql = "SELECT rowid, label, category FROM ".MAIN_DB_PREFIX."kundenkarte_medium_type WHERE active = 1 ORDER BY category, label";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
$mediumTypes[$obj->rowid] = $obj->label;
|
|
}
|
|
}
|
|
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="id" value="'.$id.'">';
|
|
print '<input type="hidden" name="socid" value="'.$socId.'">';
|
|
print '<input type="hidden" name="contactid" value="'.$contactId.'">';
|
|
print '<input type="hidden" name="system_id" value="'.$systemId.'">';
|
|
print '<input type="hidden" name="action" value="'.($id > 0 ? 'update' : 'add').'">';
|
|
|
|
print load_fiche_titre($title, '', 'object_kundenkarte@kundenkarte');
|
|
|
|
print '<table class="border centpercent">';
|
|
|
|
// Source
|
|
print '<tr><td class="titlefield fieldrequired">'.$langs->trans('Von (Quelle)').'</td>';
|
|
print '<td><select name="fk_source" id="fk_source" class="flat minwidth300">';
|
|
print '<option value="">-- Quelle wählen --</option>';
|
|
foreach ($anlagenList as $aid => $ainfo) {
|
|
$selected = ($connection->fk_source == $aid || $sourceId == $aid) ? ' selected' : '';
|
|
print '<option value="'.$aid.'" data-picto="'.dol_escape_htmltag($ainfo['picto']).'"'.$selected.'>'.dol_escape_htmltag($ainfo['label']).'</option>';
|
|
}
|
|
print '</select></td></tr>';
|
|
|
|
// Target
|
|
print '<tr><td class="fieldrequired">'.$langs->trans('Nach (Ziel)').'</td>';
|
|
print '<td><select name="fk_target" id="fk_target" class="flat minwidth300">';
|
|
print '<option value="">-- Ziel wählen --</option>';
|
|
foreach ($anlagenList as $aid => $ainfo) {
|
|
$selected = ($connection->fk_target == $aid) ? ' selected' : '';
|
|
print '<option value="'.$aid.'" data-picto="'.dol_escape_htmltag($ainfo['picto']).'"'.$selected.'>'.dol_escape_htmltag($ainfo['label']).'</option>';
|
|
}
|
|
print '</select></td></tr>';
|
|
|
|
// Medium type
|
|
print '<tr><td>'.$langs->trans('Kabeltyp').'</td>';
|
|
print '<td><select name="fk_medium_type" class="flat minwidth200">';
|
|
print '<option value="">-- oder Freitext unten --</option>';
|
|
foreach ($mediumTypes as $mid => $mlabel) {
|
|
$selected = ($connection->fk_medium_type == $mid) ? ' selected' : '';
|
|
print '<option value="'.$mid.'"'.$selected.'>'.dol_escape_htmltag($mlabel).'</option>';
|
|
}
|
|
print '</select></td></tr>';
|
|
|
|
// Medium type text (free text)
|
|
print '<tr><td>'.$langs->trans('Kabeltyp (Freitext)').'</td>';
|
|
print '<td><input type="text" name="medium_type_text" class="flat minwidth300" value="'.dol_escape_htmltag($connection->medium_type_text).'" placeholder="z.B. NYM-J"></td></tr>';
|
|
|
|
// Medium spec
|
|
print '<tr><td>'.$langs->trans('Querschnitt/Typ').'</td>';
|
|
print '<td><input type="text" name="medium_spec" class="flat minwidth200" value="'.dol_escape_htmltag($connection->medium_spec).'" placeholder="z.B. 5x2,5mm²"></td></tr>';
|
|
|
|
// Length
|
|
print '<tr><td>'.$langs->trans('Länge').'</td>';
|
|
print '<td><input type="text" name="medium_length" class="flat minwidth150" value="'.dol_escape_htmltag($connection->medium_length).'" placeholder="z.B. 15m"></td></tr>';
|
|
|
|
// Color
|
|
print '<tr><td>'.$langs->trans('Farbe').'</td>';
|
|
print '<td><input type="text" name="medium_color" class="flat minwidth150" value="'.dol_escape_htmltag($connection->medium_color).'" placeholder="z.B. grau"></td></tr>';
|
|
|
|
// Label
|
|
print '<tr><td>'.$langs->trans('Bezeichnung').'</td>';
|
|
print '<td><input type="text" name="label" class="flat minwidth300" value="'.dol_escape_htmltag($connection->label).'" placeholder="z.B. Zuleitung HAK"></td></tr>';
|
|
|
|
// Route description
|
|
print '<tr><td>'.$langs->trans('Verlegungsweg').'</td>';
|
|
print '<td><textarea name="route_description" class="flat" rows="3" style="width:90%;">'.dol_escape_htmltag($connection->route_description).'</textarea></td></tr>';
|
|
|
|
// Installation date
|
|
print '<tr><td>'.$langs->trans('Installationsdatum').'</td>';
|
|
print '<td><input type="date" name="installation_date" class="flat" value="'.dol_escape_htmltag($connection->installation_date).'"></td></tr>';
|
|
|
|
print '</table>';
|
|
|
|
print '<div class="center" style="margin-top:20px;">';
|
|
print '<button type="submit" class="button button-save">'.$langs->trans('Save').'</button>';
|
|
print ' <a class="button button-cancel" href="'.$backUrl.'">'.$langs->trans('Cancel').'</a>';
|
|
|
|
if ($id > 0 && $user->hasRight('kundenkarte', 'write')) {
|
|
print ' <a class="button button-delete" style="margin-left:20px;" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&socid='.$socId.'&contactid='.$contactId.'&system_id='.$systemId.'&action=delete&token='.newToken().'" onclick="return confirm(\'Verbindung wirklich löschen?\');">'.$langs->trans('Delete').'</a>';
|
|
}
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
|
|
// Select2 mit Icons für Quelle/Ziel-Dropdowns
|
|
print '<script>
|
|
$(document).ready(function() {
|
|
function formatAnlageOption(option) {
|
|
if (!option.id) return option.text;
|
|
var picto = $(option.element).data("picto");
|
|
if (picto) {
|
|
return $("<span><i class=\"fa " + picto + "\" style=\"width:20px;margin-right:8px;text-align:center;color:#666;\"></i>" + $("<span>").text(option.text).html() + "</span>");
|
|
}
|
|
return option.text;
|
|
}
|
|
$("#fk_source, #fk_target").select2({
|
|
templateResult: formatAnlageOption,
|
|
templateSelection: formatAnlageOption,
|
|
width: "100%",
|
|
placeholder: "-- Gerät wählen --",
|
|
allowClear: true
|
|
});
|
|
});
|
|
</script>';
|
|
|
|
llxFooter();
|
|
$db->close();
|