false, 'error' => 'Dolibarr not loaded'))); } header('Content-Type: application/json; charset=UTF-8'); $response = array('success' => false); // Verify token $token = GETPOST('token', 'none'); if (empty($token)) { echo json_encode(array('success' => false, 'error' => 'Nicht authentifiziert')); exit; } $tokenData = json_decode(base64_decode($token), true); if (!$tokenData || empty($tokenData['user_id']) || empty($tokenData['expires']) || $tokenData['expires'] < time()) { echo json_encode(array('success' => false, 'error' => 'Token ungültig oder abgelaufen')); exit; } // Verify hash $expectedHash = md5($tokenData['user_id'] . $tokenData['login'] . getDolGlobalString('MAIN_SECURITY_SALT', 'defaultsalt')); if ($tokenData['hash'] !== $expectedHash) { echo json_encode(array('success' => false, 'error' => 'Token manipuliert')); exit; } // Load user require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; $user = new User($db); $user->fetch($tokenData['user_id']); $user->getrights(); if ($user->id <= 0 || $user->statut != 1) { echo json_encode(array('success' => false, 'error' => 'Benutzer nicht mehr aktiv')); exit; } // Check permission if (!$user->hasRight('kundenkarte', 'read')) { echo json_encode(array('success' => false, 'error' => 'Keine Berechtigung')); exit; } // Load required classes require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/anlage.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentpanel.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentcarrier.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipment.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmenttype.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/equipmentconnection.class.php'; require_once DOL_DOCUMENT_ROOT.'/custom/kundenkarte/class/mediumtype.class.php'; $action = GETPOST('action', 'aZ09'); switch ($action) { // ============================================ // CUSTOMER SEARCH // ============================================ case 'search_customers': $query = GETPOST('query', 'alphanohtml'); if (strlen($query) < 2) { $response['error'] = 'Mindestens 2 Zeichen'; break; } $sql = "SELECT s.rowid, s.nom as name, s.town"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE s.entity IN (".getEntity('societe').")"; $sql .= " AND s.status = 1"; $sql .= " AND (s.nom LIKE '%".$db->escape($query)."%'"; $sql .= " OR s.name_alias LIKE '%".$db->escape($query)."%')"; $sql .= " ORDER BY s.nom ASC"; $sql .= " LIMIT 30"; $resql = $db->query($sql); $customers = array(); if ($resql) { while ($obj = $db->fetch_object($resql)) { $customers[] = array( 'id' => $obj->rowid, 'name' => $obj->name, 'town' => $obj->town ); } } $response['success'] = true; $response['customers'] = $customers; break; // ============================================ // GET ANLAGEN FOR CUSTOMER (inkl. Kontakt-Adressen) // ============================================ case 'get_anlagen': $customerId = GETPOSTINT('customer_id'); if ($customerId <= 0) { $response['error'] = 'Keine Kunden-ID'; break; } // Feld-Metadaten laden (show_in_tree Felder für Anzeige) $fieldMeta = array(); $sqlFields = "SELECT fk_anlage_type, field_code, field_label, tree_display_mode, badge_color, show_in_tree, field_type"; $sqlFields .= " FROM ".MAIN_DB_PREFIX."kundenkarte_anlage_type_field"; $sqlFields .= " WHERE active = 1 AND show_in_tree = 1"; $sqlFields .= " ORDER BY position"; $resFields = $db->query($sqlFields); if ($resFields) { while ($fObj = $db->fetch_object($resFields)) { if ($fObj->field_type === 'header') continue; $fieldMeta[(int)$fObj->fk_anlage_type][$fObj->field_code] = array( 'label' => $fObj->field_label, 'display' => $fObj->tree_display_mode ?: 'badge', 'color' => $fObj->badge_color ?: '', ); } $db->free($resFields); } // Kompletter Baum ohne Kontaktzuweisung (Kunden-Ebene) $anlage = new Anlage($db); $tree = $anlage->fetchTree($customerId, 0); $result = pwaTreeToArray($tree, $fieldMeta); // Kontakt-Adressen mit Anlagen laden $contacts = array(); $sql = "SELECT c.rowid, c.lastname, c.firstname, c.address, c.town,"; $sql .= " (SELECT COUNT(*) FROM ".MAIN_DB_PREFIX."kundenkarte_anlage a WHERE a.fk_contact = c.rowid AND a.status = 1) as anlage_count"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as c"; $sql .= " WHERE c.fk_soc = ".((int) $customerId); $sql .= " AND c.statut = 1"; $sql .= " ORDER BY c.lastname ASC"; $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $contactName = trim($obj->lastname.' '.$obj->firstname); $contacts[] = array( 'id' => $obj->rowid, 'name' => $contactName, 'address' => $obj->address, 'town' => $obj->town, 'anlage_count' => (int) $obj->anlage_count ); } } $response['success'] = true; $response['anlagen'] = $result; $response['contacts'] = $contacts; break; // ============================================ // GET ANLAGEN FOR CONTACT ADDRESS // ============================================ case 'get_contact_anlagen': $customerId = GETPOSTINT('customer_id'); $contactId = GETPOSTINT('contact_id'); if ($customerId <= 0 || $contactId <= 0) { $response['error'] = 'Kunden-ID und Kontakt-ID erforderlich'; break; } // Feld-Metadaten laden falls nicht schon vorhanden if (!isset($fieldMeta)) { $fieldMeta = array(); $sqlFields = "SELECT fk_anlage_type, field_code, field_label, tree_display_mode, badge_color, show_in_tree, field_type"; $sqlFields .= " FROM ".MAIN_DB_PREFIX."kundenkarte_anlage_type_field"; $sqlFields .= " WHERE active = 1 AND show_in_tree = 1"; $sqlFields .= " ORDER BY position"; $resFields = $db->query($sqlFields); if ($resFields) { while ($fObj = $db->fetch_object($resFields)) { if ($fObj->field_type === 'header') continue; $fieldMeta[(int)$fObj->fk_anlage_type][$fObj->field_code] = array( 'label' => $fObj->field_label, 'display' => $fObj->tree_display_mode ?: 'badge', 'color' => $fObj->badge_color ?: '', ); } $db->free($resFields); } } $anlage = new Anlage($db); $tree = $anlage->fetchTreeByContact($customerId, $contactId, 0); $result = pwaTreeToArray($tree, $fieldMeta); $response['success'] = true; $response['anlagen'] = $result; break; // ============================================ // GET ANLAGE DATA (Panels, Carriers, Equipment) // ============================================ case 'get_anlage_data': $anlageId = GETPOSTINT('anlage_id'); if ($anlageId <= 0) { $response['error'] = 'Keine Anlagen-ID'; break; } // Load panels $panel = new EquipmentPanel($db); $panels = $panel->fetchByAnlage($anlageId); $panelsData = array(); foreach ($panels as $p) { $panelsData[] = array( 'id' => $p->id, 'label' => $p->label, 'position' => $p->position ); } // Load carriers $carrier = new EquipmentCarrier($db); $carriersData = array(); foreach ($panels as $p) { $p->fetchCarriers(); foreach ($p->carriers as $c) { $carriersData[] = array( 'id' => $c->id, 'fk_panel' => $c->fk_panel, 'label' => $c->label, 'total_te' => $c->total_te, 'position' => $c->position ); } } // Load equipment $equipment = new Equipment($db); $equipmentData = array(); foreach ($carriersData as $c) { $items = $equipment->fetchByCarrier($c['id']); foreach ($items as $eq) { $equipmentData[] = array( 'id' => $eq->id, 'fk_carrier' => $eq->fk_carrier, 'fk_equipment_type' => $eq->fk_equipment_type, '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() ); } } // Equipment-Typen laden (benötigt für Terminal-Position-Auflösung) $eqType = new EquipmentType($db); $types = $eqType->fetchAllBySystem(1, 1); // System 1 = Elektro, nur aktive // Abgänge laden (Connections mit fk_target IS NULL = Ausgänge) $outputsData = array(); if (!empty($equipmentData)) { $equipmentIds = array_map(function($e) { return (int) $e['id']; }, $equipmentData); $sql = "SELECT rowid, fk_source, output_label, medium_type, medium_spec, medium_length, connection_type, color, source_terminal, source_terminal_id"; $sql .= " FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_connection"; $sql .= " WHERE fk_source IN (".implode(',', $equipmentIds).")"; $sql .= " AND fk_target IS NULL"; $sql .= " AND status = 1"; $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { // Position bestimmen wie Website: source_terminal_id → Terminal-Config $isTop = false; if ($obj->source_terminal === 'top') { // PWA-erstellte Verbindung mit expliziter Top-Angabe $isTop = true; } elseif (!empty($obj->source_terminal_id)) { // Website-erstellte Verbindung: Terminal-Position aus Equipment-Typ ermitteln $termId = $obj->source_terminal_id; $eqTypeId = null; foreach ($equipmentData as $e) { if ($e['id'] == $obj->fk_source) { $eqTypeId = $e['fk_equipment_type']; break; } } if ($eqTypeId) { // Terminal-Config des Typs prüfen $termResolved = false; foreach ($types as $t) { if ($t->id == $eqTypeId && !empty($t->terminals_config)) { $config = json_decode($t->terminals_config, true); $terms = $config['terminals'] ?? ($config['inputs'] ?? []); if (!empty($config['terminals'])) { foreach ($config['terminals'] as $term) { if ($term['id'] === $termId) { $isTop = ($term['pos'] === 'top'); $termResolved = true; break; } } } break; } } // Fallback: t1=oben, t2=unten (Standard LS) if (!$termResolved) { $isTop = ($termId === 't1'); } } } $outputsData[] = array( 'id' => $obj->rowid, 'fk_source' => $obj->fk_source, 'output_label' => $obj->output_label, 'medium_type' => $obj->medium_type, 'medium_spec' => $obj->medium_spec, 'medium_length' => $obj->medium_length, 'connection_type' => $obj->connection_type, 'color' => $obj->color, 'source_terminal_id' => $obj->source_terminal_id ?: '', 'is_top' => $isTop ); } } } // Einspeisungen laden (Connections mit fk_source IS NULL = Inputs) $inputsData = array(); if (!empty($equipmentData)) { $sql = "SELECT rowid, fk_target, output_label, connection_type, color"; $sql .= " FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_connection"; $sql .= " WHERE fk_target IN (".implode(',', $equipmentIds).")"; $sql .= " AND fk_source IS NULL"; $sql .= " AND status = 1"; $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $inputsData[] = array( 'id' => $obj->rowid, 'fk_target' => $obj->fk_target, 'output_label' => $obj->output_label, 'connection_type' => $obj->connection_type, 'color' => $obj->color ); } } } // Equipment-Typen für Response aufbereiten (bereits oben geladen) $typesData = array(); foreach ($types as $t) { $typesData[] = array( 'id' => $t->id, 'ref' => $t->ref, 'label' => $t->label, 'label_short' => $t->label_short, 'width_te' => $t->width_te, 'color' => $t->color ); } $response['success'] = true; $response['panels'] = $panelsData; $response['carriers'] = $carriersData; $response['equipment'] = $equipmentData; $response['outputs'] = $outputsData; $response['inputs'] = $inputsData; $response['types'] = $typesData; break; // ============================================ // CREATE PANEL // ============================================ case 'create_panel': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $anlageId = GETPOSTINT('anlage_id'); $label = GETPOST('label', 'alphanohtml'); if ($anlageId <= 0) { $response['error'] = 'Keine Anlagen-ID'; break; } $panel = new EquipmentPanel($db); $panel->fk_anlage = $anlageId; $panel->label = $label ?: 'Feld'; $result = $panel->create($user); if ($result > 0) { $response['success'] = true; $response['panel_id'] = $result; } else { $response['error'] = $panel->error ?: 'Fehler beim Anlegen'; } break; // ============================================ // CREATE CARRIER // ============================================ case 'create_carrier': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $panelId = GETPOSTINT('panel_id'); $totalTe = GETPOSTINT('total_te') ?: 12; $label = GETPOST('label', 'alphanohtml'); if ($panelId <= 0) { $response['error'] = 'Keine Panel-ID'; break; } // Anlage-ID vom Panel holen (benötigt für Carrier-Erstellung) $panelObj = new EquipmentPanel($db); if ($panelObj->fetch($panelId) <= 0) { $response['error'] = 'Panel nicht gefunden'; break; } $carrier = new EquipmentCarrier($db); $carrier->fk_anlage = $panelObj->fk_anlage; $carrier->fk_panel = $panelId; $carrier->label = $label ?: 'Hutschiene'; $carrier->total_te = $totalTe; $result = $carrier->create($user); if ($result > 0) { $response['success'] = true; $response['carrier_id'] = $result; } else { $response['error'] = $carrier->error ?: 'Fehler beim Anlegen'; } break; // ============================================ // UPDATE CARRIER // ============================================ case 'update_carrier': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $carrierId = GETPOSTINT('carrier_id'); if ($carrierId <= 0) { $response['error'] = 'Keine Carrier-ID'; break; } $carrier = new EquipmentCarrier($db); if ($carrier->fetch($carrierId) <= 0) { $response['error'] = 'Hutschiene nicht gefunden'; break; } $carrier->label = GETPOST('label', 'alphanohtml') ?: $carrier->label; $newTe = GETPOSTINT('total_te'); if ($newTe > 0) { $carrier->total_te = $newTe; } $result = $carrier->update($user); if ($result > 0) { $response['success'] = true; } else { $response['error'] = $carrier->error ?: 'Fehler beim Aktualisieren'; } break; // ============================================ // DELETE CARRIER // ============================================ case 'delete_carrier': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $carrierId = GETPOSTINT('carrier_id'); if ($carrierId <= 0) { $response['error'] = 'Keine Carrier-ID'; break; } $carrier = new EquipmentCarrier($db); if ($carrier->fetch($carrierId) <= 0) { $response['error'] = 'Hutschiene nicht gefunden'; break; } $result = $carrier->delete($user); if ($result > 0) { $response['success'] = true; } else { $response['error'] = $carrier->error ?: 'Fehler beim Löschen'; } break; // ============================================ // CREATE EQUIPMENT // ============================================ case 'create_equipment': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $carrierId = GETPOSTINT('carrier_id'); $typeId = GETPOSTINT('type_id'); $label = GETPOST('label', 'alphanohtml'); $positionTe = GETPOSTINT('position_te') ?: 1; $fieldValues = GETPOST('field_values', 'nohtml'); if ($carrierId <= 0 || $typeId <= 0) { $response['error'] = 'Carrier-ID und Typ-ID erforderlich'; break; } // Load type for width $eqType = new EquipmentType($db); $eqType->fetch($typeId); $equipment = new Equipment($db); $equipment->fk_carrier = $carrierId; $equipment->fk_equipment_type = $typeId; $equipment->label = $label; $equipment->position_te = $positionTe; $equipment->width_te = $eqType->width_te ?: 1; $equipment->field_values = $fieldValues; // Bezeichnung automatisch generieren wenn leer (wie Website) if (empty(trim($equipment->label ?? ''))) { $carrier = new EquipmentCarrier($db); if ($carrier->fetch($carrierId) > 0) { $carrierLabel = $carrier->label ?: ('R'.$carrier->id); $posStart = $equipment->position_te; $posEnd = $posStart + $equipment->width_te - 1; if ($equipment->width_te > 1) { $equipment->label = $carrierLabel.'.'.$posStart.'-'.$posEnd; } else { $equipment->label = $carrierLabel.'.'.$posStart; } } } $result = $equipment->create($user); if ($result > 0) { $response['success'] = true; $response['equipment_id'] = $result; $response['label'] = $equipment->label; $response['block_label'] = $equipment->getBlockLabel(); $response['block_color'] = $equipment->getBlockColor(); } else { $response['error'] = $equipment->error ?: 'Fehler beim Anlegen'; } break; // ============================================ // GET TYPE FIELDS (Felder pro Equipment-Typ) // ============================================ case 'get_type_fields': $typeId = GETPOSTINT('type_id'); $equipmentId = GETPOSTINT('equipment_id'); if ($typeId <= 0) { $response['error'] = 'Keine Typ-ID'; break; } $type = new EquipmentType($db); if ($type->fetch($typeId) <= 0) { $response['error'] = 'Typ nicht gefunden'; break; } $fields = $type->fetchFields(1); // Bestehende Werte laden (bei Bearbeitung) $existingValues = array(); if ($equipmentId > 0) { $eq = new Equipment($db); if ($eq->fetch($equipmentId) > 0) { $existingValues = $eq->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' => (int) $field->required, 'show_on_block' => (int) $field->show_on_block, 'value' => $value ); } $response['success'] = true; $response['fields'] = $result; break; // ============================================ // UPDATE EQUIPMENT // ============================================ case 'update_equipment': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $equipmentId = GETPOSTINT('equipment_id'); $label = GETPOST('label', 'alphanohtml'); $fieldValues = GETPOST('field_values', 'nohtml'); if ($equipmentId <= 0) { $response['error'] = 'Keine Equipment-ID'; break; } $equipment = new Equipment($db); if ($equipment->fetch($equipmentId) <= 0) { $response['error'] = 'Automat nicht gefunden'; break; } $equipment->label = $label; $equipment->field_values = $fieldValues; $result = $equipment->update($user); if ($result > 0) { $response['success'] = true; // Aktualisierte Daten zurückgeben $response['block_label'] = $equipment->getBlockLabel(); $response['block_color'] = $equipment->getBlockColor(); } else { $response['error'] = $equipment->error ?: 'Fehler beim Aktualisieren'; } break; // ============================================ // DELETE EQUIPMENT // ============================================ case 'delete_equipment': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $equipmentId = GETPOSTINT('equipment_id'); if ($equipmentId <= 0) { $response['error'] = 'Keine Equipment-ID'; break; } $equipment = new Equipment($db); if ($equipment->fetch($equipmentId) <= 0) { $response['error'] = 'Automat nicht gefunden'; break; } $result = $equipment->delete($user); if ($result > 0) { $response['success'] = true; } else { $response['error'] = $equipment->error ?: 'Fehler beim Löschen'; } break; // ============================================ // CREATE CONNECTION (Abgang oder Einspeisung) // ============================================ case 'create_connection': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $equipmentId = GETPOSTINT('equipment_id'); $direction = GETPOST('direction', 'alpha'); // 'output' oder 'input' $connectionType = GETPOST('connection_type', 'alphanohtml'); $outputLabel = GETPOST('output_label', 'alphanohtml'); $mediumType = GETPOST('medium_type', 'alphanohtml'); $mediumSpec = GETPOST('medium_spec', 'alphanohtml'); $mediumLength = GETPOST('medium_length', 'alphanohtml'); $sourceTerminal = GETPOST('source_terminal', 'alphanohtml') ?: 'output'; $sourceTerminalId = GETPOST('source_terminal_id', 'alphanohtml'); if ($equipmentId <= 0) { $response['error'] = 'Keine Equipment-ID'; break; } // Equipment prüfen und Carrier-ID ermitteln $eq = new Equipment($db); if ($eq->fetch($equipmentId) <= 0) { $response['error'] = 'Automat nicht gefunden'; break; } $conn = new EquipmentConnection($db); $conn->connection_type = $connectionType; $conn->color = GETPOST('color', 'alphanohtml'); $conn->output_label = $outputLabel; $conn->fk_carrier = $eq->fk_carrier; if ($direction === 'input') { // Einspeisung: fk_source = NULL, fk_target = Equipment $conn->fk_target = $equipmentId; $conn->fk_source = null; $conn->target_terminal = 'input'; } else { // Abgang: fk_source = Equipment, fk_target = NULL $conn->fk_source = $equipmentId; $conn->fk_target = null; $conn->source_terminal = $sourceTerminal; $conn->source_terminal_id = $sourceTerminalId ?: ($sourceTerminal === 'top' ? 't1' : 't2'); $conn->medium_type = $mediumType; $conn->medium_spec = $mediumSpec; $conn->medium_length = $mediumLength; } $result = $conn->create($user); if ($result > 0) { $response['success'] = true; $response['connection_id'] = $result; } else { $response['error'] = $conn->error ?: 'Fehler beim Anlegen'; } break; // ============================================ // UPDATE CONNECTION // ============================================ case 'update_connection': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $connectionId = GETPOSTINT('connection_id'); if ($connectionId <= 0) { $response['error'] = 'Keine Verbindungs-ID'; break; } $conn = new EquipmentConnection($db); if ($conn->fetch($connectionId) <= 0) { $response['error'] = 'Verbindung nicht gefunden'; break; } $conn->connection_type = GETPOST('connection_type', 'alphanohtml'); $conn->color = GETPOST('color', 'alphanohtml'); $conn->output_label = GETPOST('output_label', 'alphanohtml'); $conn->medium_type = GETPOST('medium_type', 'alphanohtml'); $conn->medium_spec = GETPOST('medium_spec', 'alphanohtml'); $conn->medium_length = GETPOST('medium_length', 'alphanohtml'); if (GETPOSTISSET('source_terminal')) { $conn->source_terminal = GETPOST('source_terminal', 'alphanohtml') ?: $conn->source_terminal; } if (GETPOSTISSET('source_terminal_id')) { $conn->source_terminal_id = GETPOST('source_terminal_id', 'alphanohtml') ?: $conn->source_terminal_id; } $result = $conn->update($user); if ($result > 0) { $response['success'] = true; } else { $response['error'] = $conn->error ?: 'Fehler beim Aktualisieren'; } break; // ============================================ // DELETE CONNECTION // ============================================ case 'delete_connection': if (!$user->hasRight('kundenkarte', 'write')) { $response['error'] = 'Keine Schreibberechtigung'; break; } $connectionId = GETPOSTINT('connection_id'); if ($connectionId <= 0) { $response['error'] = 'Keine Verbindungs-ID'; break; } $conn = new EquipmentConnection($db); if ($conn->fetch($connectionId) <= 0) { $response['error'] = 'Verbindung nicht gefunden'; break; } $result = $conn->delete($user); if ($result > 0) { $response['success'] = true; } else { $response['error'] = $conn->error ?: 'Fehler beim Löschen'; } break; // ============================================ // GET MEDIUM TYPES (Kabeltypen aus DB) // ============================================ case 'get_medium_types': $mediumType = new MediumType($db); $grouped = $mediumType->fetchGroupedByCategory(1); // System 1 = Elektro $result = array(); foreach ($grouped as $category => $types) { $catTypes = array(); foreach ($types as $t) { $catTypes[] = array( 'ref' => $t->ref, 'label' => $t->label, 'default_spec' => $t->default_spec, 'available_specs' => $t->getAvailableSpecsArray(), ); } $result[] = array( 'category' => $category, 'category_label' => $types[0]->getCategoryLabel(), 'types' => $catTypes ); } $response['success'] = true; $response['groups'] = $result; break; default: $response['error'] = 'Unbekannte Aktion: ' . $action; } echo json_encode($response); $db->close(); /** * Feld-Badges für eine Anlage aufbereiten (show_in_tree Felder) * * @param Anlage $anlage Anlage-Objekt * @param array $fieldMeta Feld-Metadaten [typeId][code] = {label, display, color} * @return array Array von Feld-Objekten mit label, value, color */ function pwaGetAnlageFields($anlage, $fieldMeta) { $result = array(); $values = $anlage->getFieldValues(); if (empty($values)) return $result; $typeId = (int) $anlage->fk_anlage_type; $meta = isset($fieldMeta[$typeId]) ? $fieldMeta[$typeId] : array(); if (empty($meta)) return $result; foreach ($meta as $code => $fm) { $val = isset($values[$code]) ? $values[$code] : null; if ($val === '' || $val === null) continue; $result[] = array( 'label' => $fm['label'], 'value' => $val, 'color' => $fm['color'], 'display' => $fm['display'], ); } return $result; } /** * Anlagen-Baum rekursiv in JSON-Array umwandeln * * @param array $nodes Array von Anlage-Objekten mit ->children * @param array $fieldMeta Feld-Metadaten [typeId][code] = {label, display, color} * @return array JSON-serialisierbares Array mit children */ function pwaTreeToArray($nodes, $fieldMeta) { $result = array(); foreach ($nodes as $node) { $item = array( 'id' => $node->id, 'label' => $node->label, 'type' => $node->type_label, 'can_have_equipment' => !empty($node->type_can_have_equipment), 'can_have_children' => !empty($node->type_can_have_children), ); // Feld-Badges $fields = pwaGetAnlageFields($node, $fieldMeta); if (!empty($fields)) { $item['fields'] = $fields; } // Kinder rekursiv if (!empty($node->children)) { $item['children'] = pwaTreeToArray($node->children, $fieldMeta); } $result[] = $item; } return $result; }