* * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file netdiag/api/protocols.php * \ingroup netdiag * \brief API-Endpunkt: Protokolle lesen (GET ?id=) und synchronisieren * (POST action=sync). Der Sync ist idempotent über client_uuid. */ require_once __DIR__.'/netdiag_api.lib.php'; netdiag_api_bootstrap(); /** * @var Conf $conf * @var DoliDB $db * @var Translate $langs */ $user = netdiag_api_authenticate($db); require_once __DIR__.'/../class/netdiagprotocol.class.php'; require_once __DIR__.'/../class/netdiagdevice.class.php'; require_once __DIR__.'/../class/netdiagmeasurement.class.php'; // ========================================================================= // GET: einzelnes Protokoll mit Geräten und Messungen // ========================================================================= if ($_SERVER['REQUEST_METHOD'] === 'GET') { $id = isset($_GET['id']) ? (int) $_GET['id'] : 0; if ($id <= 0) { netdiag_api_error('Parameter id fehlt', 400); } $protocol = new NetDiagProtocol($db); if ($protocol->fetch($id) <= 0) { netdiag_api_error('Protokoll nicht gefunden', 404); } $devObj = new NetDiagDevice($db); $devices = array(); foreach ($devObj->fetchAllByProtocol($protocol->id) as $d) { $devices[] = array( 'id' => (int) $d->id, 'ip' => $d->ip, 'mac' => $d->mac, 'hostname' => $d->hostname, 'vendor' => $d->vendor, 'deviceType' => $d->devicetype, 'note' => $d->note, ); } $measObj = new NetDiagMeasurement($db); $measurements = array(); foreach ($measObj->fetchAllByProtocol($protocol->id) as $m) { $measurements[] = array( 'id' => (int) $m->id, 'deviceId' => $m->fk_device ? (int) $m->fk_device : null, 'tool' => $m->tool, 'category' => $m->category, 'label' => $m->label, 'params' => $m->params ? json_decode($m->params, true) : null, 'result' => $m->result ? json_decode($m->result, true) : null, 'measureStatus' => (int) $m->measure_status, 'dateMeasure' => $db->jdate($m->date_measure), ); } netdiag_api_respond(array( 'protocol' => array( 'id' => (int) $protocol->id, 'ref' => $protocol->ref, 'label' => $protocol->label, 'clientUuid' => $protocol->client_uuid, 'socId' => $protocol->fk_soc ? (int) $protocol->fk_soc : null, 'orderId' => $protocol->fk_commande ? (int) $protocol->fk_commande : null, 'dateDiag' => $db->jdate($protocol->date_diag), 'location' => $protocol->standort, 'subnet' => $protocol->subnet, 'status' => (int) $protocol->status, 'note' => $protocol->note, ), 'devices' => $devices, 'measurements' => $measurements, )); } // ========================================================================= // POST: Protokoll synchronisieren (anlegen oder aktualisieren) // ========================================================================= if ($_SERVER['REQUEST_METHOD'] !== 'POST') { netdiag_api_error('Methode nicht erlaubt', 405); } if (!$user->hasRight('netdiag', 'protocol', 'write')) { netdiag_api_error('Keine Schreibberechtigung', 403); } $body = netdiag_api_read_body(); if (($body['action'] ?? '') !== 'sync' || empty($body['protocol']) || !is_array($body['protocol'])) { netdiag_api_error('Erwartet: { action: "sync", protocol: {...} }', 400); } $p = $body['protocol']; $uuid = isset($p['clientUuid']) ? trim((string) $p['clientUuid']) : ''; if ($uuid === '') { netdiag_api_error('protocol.clientUuid erforderlich', 400); } $db->begin(); // Vorhandenes Protokoll über UUID suchen (idempotent) $protocol = new NetDiagProtocol($db); $exists = $protocol->fetchByClientUuid($uuid); if ($exists < 0) { $db->rollback(); netdiag_api_error('Datenbankfehler beim Laden', 500); } $protocol->client_uuid = $uuid; $protocol->label = isset($p['label']) ? (string) $p['label'] : ''; $protocol->fk_soc = !empty($p['socId']) ? (int) $p['socId'] : null; $protocol->fk_commande = !empty($p['orderId']) ? (int) $p['orderId'] : null; $protocol->date_diag = netdiag_api_timestamp($p['dateDiag'] ?? 0); $protocol->fk_user_techniker = (int) $user->id; $protocol->standort = isset($p['location']) ? (string) $p['location'] : ''; $protocol->subnet = isset($p['subnet']) ? (string) $p['subnet'] : ''; $protocol->status = isset($p['status']) ? (int) $p['status'] : NetDiagProtocol::STATUS_DRAFT; $protocol->note = isset($p['note']) ? (string) $p['note'] : ''; // tms explizit setzen — die Spalte ist NOT NULL ohne brauchbaren NULL-Default // (explicit_defaults_for_timestamp=1), createCommon würde sonst NULL einfügen. $protocol->tms = dol_now(); if ($exists > 0) { $result = $protocol->update($user, 1); } else { $result = $protocol->create($user, 1); } if ($result <= 0) { $db->rollback(); netdiag_api_error('Protokoll speichern fehlgeschlagen: '.$protocol->errorsToString(), 500); } $protocolId = (int) $protocol->id; // Alte Geräte und Messungen entfernen (Sync ersetzt komplett) $db->query("DELETE FROM ".$db->prefix()."netdiag_measurement WHERE fk_protocol = ".$protocolId); $db->query("DELETE FROM ".$db->prefix()."netdiag_device WHERE fk_protocol = ".$protocolId); // Geräte einfügen, dabei clientId -> serverRowid merken $deviceIdMap = array(); $devicesIn = (!empty($p['devices']) && is_array($p['devices'])) ? $p['devices'] : array(); foreach ($devicesIn as $d) { $dev = new NetDiagDevice($db); $dev->fk_protocol = $protocolId; $dev->ip = isset($d['ip']) ? (string) $d['ip'] : ''; $dev->mac = isset($d['mac']) ? (string) $d['mac'] : ''; $dev->hostname = isset($d['hostname']) ? (string) $d['hostname'] : ''; $dev->vendor = isset($d['vendor']) ? (string) $d['vendor'] : ''; $dev->devicetype = isset($d['deviceType']) ? (string) $d['deviceType'] : ''; $dev->note = isset($d['note']) ? (string) $d['note'] : ''; $dev->tms = dol_now(); if ($dev->create($user, 1) <= 0) { $db->rollback(); netdiag_api_error('Gerät speichern fehlgeschlagen: '.$dev->errorsToString(), 500); } if (isset($d['clientId'])) { $deviceIdMap[(string) $d['clientId']] = (int) $dev->id; } } // Messungen einfügen, deviceClientId auf serverRowid abbilden $measIn = (!empty($p['measurements']) && is_array($p['measurements'])) ? $p['measurements'] : array(); foreach ($measIn as $m) { $meas = new NetDiagMeasurement($db); $meas->fk_protocol = $protocolId; $dcid = isset($m['deviceClientId']) ? (string) $m['deviceClientId'] : ''; $meas->fk_device = ($dcid !== '' && isset($deviceIdMap[$dcid])) ? $deviceIdMap[$dcid] : null; $meas->tool = isset($m['tool']) ? (string) $m['tool'] : 'unknown'; $meas->category = isset($m['category']) ? (string) $m['category'] : ''; $meas->label = isset($m['label']) ? (string) $m['label'] : ''; $meas->params = isset($m['params']) ? json_encode($m['params'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null; $meas->result = isset($m['result']) ? json_encode($m['result'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null; $meas->measure_status = isset($m['measureStatus']) ? (int) $m['measureStatus'] : 0; $meas->date_measure = netdiag_api_timestamp($m['dateMeasure'] ?? 0); $meas->tms = dol_now(); if ($meas->create($user, 1) <= 0) { $db->rollback(); netdiag_api_error('Messung speichern fehlgeschlagen: '.$meas->errorsToString(), 500); } } $db->commit(); // PDF neu erzeugen, wenn das Protokoll abgeschlossen ist $pdfgenerated = false; if ($protocol->status == NetDiagProtocol::STATUS_DONE) { require_once __DIR__.'/../lib/netdiag_pdf.lib.php'; $pdfgenerated = (netdiagGeneratePdf($db, $protocol, $langs) > 0); } netdiag_api_respond(array( 'ok' => true, 'protocolId' => $protocolId, 'ref' => $protocol->ref, 'created' => ($exists == 0), 'pdfGenerated' => $pdfgenerated, ));