All checks were successful
Deploy netdiag / deploy (push) Successful in 16s
DER eigentliche Fehler: Die App schickt dateDiag/dateMeasure als JavaScript-Millisekunden (Date.now(), 13-stellig). Dolibarrs idate() erwartet Unix-Sekunden -> MySQL: "Incorrect datetime value: Bad value 1779211311036 for date" -> createCommon scheitert -> HTTP 500. Fix: netdiag_api_timestamp() rechnet ms-Zeitstempel (> 1e11) auf Sekunden um. protocols.php nutzt sie fuer date_diag und date_measure. Serverseitig bewusst — so synchronisieren auch bereits installierte App-Versionen ohne APK-Update korrekt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
220 lines
8.5 KiB
PHP
220 lines
8.5 KiB
PHP
<?php
|
|
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
|
*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \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,
|
|
));
|