dolibarr.netdiag/class/netdiagprotocol.class.php
Eduard Wisch c576726a26
Some checks are pending
Deploy netdiag / deploy (push) Waiting to run
Initiales Commit — Dolibarr-Modul NetDiag [deploy]
Netzwerk-Diagnose-Modul mit JSON-API für die NetDiag-App:
- 3 Tabellen (protocol/device/measurement), generisches JSON-result
- JSON-API: auth, customers, orders, protocols (idempotenter Sync), pdf
- JWT-Auth (HS256), CORS für die Capacitor-App
- Tabs an Thirdparty + Auftrag, Protokoll-Card, PDF-Generator
- QR-Code zum App-Download in der Modul-Konfiguration
- de_DE + en_US, Rechtesystem netdiag->protocol read/write/delete

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:12:11 +02:00

233 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 htdocs/custom/netdiag/class/netdiagprotocol.class.php
* \ingroup netdiag
* \brief Klasse für das Diagnose-Protokoll (Kopfdatensatz)
*/
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
/**
* Klasse NetDiagProtocol — ein Netzwerk-Diagnose-Vorgang beim Kunden.
*
* Bündelt gefundene Geräte (NetDiagDevice) und Messungen (NetDiagMeasurement)
* und ist mit Kunde (fk_soc) sowie optional Auftrag (fk_commande) verknüpft.
*/
class NetDiagProtocol extends CommonObject
{
/** @var string Modul-Name */
public $module = 'netdiag';
/** @var string Element-Typ */
public $element = 'netdiagprotocol';
/** @var string Datenbanktabelle (ohne Präfix) */
public $table_element = 'netdiag_protocol';
/** @var string Icon */
public $picto = 'fa-network-wired';
/** @var int 1 = Tabelle hat ein 'entity'-Feld für Multicompany */
public $ismultientitymanaged = 1;
/** Status-Konstanten */
const STATUS_DRAFT = 0;
const STATUS_DONE = 1;
/**
* @var array<string,array<string,mixed>> Felddefinitionen für die generischen CRUD-Methoden
*/
public $fields = array(
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'index' => 1, 'position' => 1),
'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'position' => 10),
'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'default' => 1, 'index' => 1, 'position' => 5),
'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 20),
'client_uuid' => array('type' => 'varchar(64)', 'label' => 'ClientUuid', 'enabled' => 1, 'visible' => 0, 'position' => 25),
'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => 1, 'index' => 1, 'position' => 30),
'fk_commande' => array('type' => 'integer:Commande:commande/class/commande.class.php', 'label' => 'Order', 'enabled' => 1, 'visible' => 1, 'index' => 1, 'position' => 35),
'date_diag' => array('type' => 'datetime', 'label' => 'DateDiag', 'enabled' => 1, 'visible' => 1, 'position' => 40),
'fk_user_techniker' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Technician', 'enabled' => 1, 'visible' => 1, 'position' => 45),
'standort' => array('type' => 'varchar(255)', 'label' => 'Location', 'enabled' => 1, 'visible' => 1, 'position' => 50),
'subnet' => array('type' => 'varchar(64)', 'label' => 'Subnet', 'enabled' => 1, 'visible' => 1, 'position' => 55),
'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'default' => 0, 'index' => 1, 'position' => 60, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Done')),
'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'visible' => 3, 'position' => 70),
'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 500),
'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 501),
'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 510),
'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'visible' => 0, 'position' => 511),
);
public $rowid;
public $ref;
public $entity;
public $label;
public $client_uuid;
public $fk_soc;
public $fk_commande;
public $date_diag;
public $fk_user_techniker;
public $standort;
public $subnet;
public $status;
public $note;
public $date_creation;
public $tms;
public $fk_user_creat;
public $fk_user_modif;
/**
* Konstruktor
*
* @param DoliDB $db Datenbank-Handler
*/
public function __construct(DoliDB $db)
{
$this->db = $db;
}
/**
* Datensatz anlegen
*
* @param User $user Benutzer
* @param int $notrigger 1 = Trigger unterdrücken
* @return int >0 wenn OK (rowid), <=0 bei Fehler
*/
public function create(User $user, $notrigger = 0)
{
if (empty($this->ref) || $this->ref == '(PROV)') {
$this->ref = $this->getNextNumRef();
}
if (empty($this->date_diag)) {
$this->date_diag = dol_now();
}
return $this->createCommon($user, $notrigger);
}
/**
* Datensatz laden
*
* @param int $id Rowid
* @param string $ref Referenz statt Rowid
* @return int >0 wenn OK, 0 wenn nicht gefunden, <0 bei Fehler
*/
public function fetch($id, $ref = null)
{
return $this->fetchCommon($id, $ref);
}
/**
* Protokoll anhand der Client-UUID laden (für idempotenten App-Sync)
*
* @param string $uuid Client-UUID
* @return int >0 wenn OK, 0 wenn nicht gefunden, <0 bei Fehler
*/
public function fetchByClientUuid($uuid)
{
$sql = "SELECT rowid FROM ".$this->db->prefix().$this->table_element;
$sql .= " WHERE client_uuid = '".$this->db->escape($uuid)."'";
$sql .= " AND entity IN (".getEntity($this->element).")";
$resql = $this->db->query($sql);
if (!$resql) {
$this->error = $this->db->lasterror();
return -1;
}
if ($obj = $this->db->fetch_object($resql)) {
return $this->fetch((int) $obj->rowid);
}
return 0;
}
/**
* Datensatz aktualisieren
*
* @param User $user Benutzer
* @param int $notrigger 1 = Trigger unterdrücken
* @return int >0 wenn OK, <=0 bei Fehler
*/
public function update(User $user, $notrigger = 0)
{
return $this->updateCommon($user, $notrigger);
}
/**
* Datensatz löschen (inkl. zugehöriger Geräte und Messungen)
*
* @param User $user Benutzer
* @param int $notrigger 1 = Trigger unterdrücken
* @return int >0 wenn OK, <=0 bei Fehler
*/
public function delete(User $user, $notrigger = 0)
{
$this->db->begin();
$tables = array('netdiag_measurement', 'netdiag_device');
foreach ($tables as $table) {
$sql = "DELETE FROM ".$this->db->prefix().$table." WHERE fk_protocol = ".((int) $this->id);
if (!$this->db->query($sql)) {
$this->error = $this->db->lasterror();
$this->db->rollback();
return -1;
}
}
$result = $this->deleteCommon($user, $notrigger);
if ($result <= 0) {
$this->db->rollback();
return -1;
}
$this->db->commit();
return 1;
}
/**
* Nächste freie Referenz ermitteln (NDjjjj-nnnn)
*
* @return string Neue Referenz
*/
public function getNextNumRef()
{
$prefix = 'ND'.dol_print_date(dol_now(), '%Y').'-';
$sql = "SELECT MAX(CAST(SUBSTRING(ref, ".(strlen($prefix) + 1).") AS UNSIGNED)) AS maxnum";
$sql .= " FROM ".$this->db->prefix().$this->table_element;
$sql .= " WHERE ref LIKE '".$this->db->escape($prefix)."%'";
$sql .= " AND entity IN (".getEntity($this->element).")";
$resql = $this->db->query($sql);
$num = 0;
if ($resql && ($obj = $this->db->fetch_object($resql))) {
$num = (int) $obj->maxnum;
}
return $prefix.sprintf('%04d', $num + 1);
}
/**
* Beschriftung des Status zurückgeben
*
* @param int $mode 0=Langtext, 1=Kurztext, 3=Picto, ...
* @return string HTML-Label
*/
public function getLibStatut($mode = 0)
{
global $langs;
$labels = array(
self::STATUS_DRAFT => $langs->trans('Draft'),
self::STATUS_DONE => $langs->trans('NetDiagStatusDone'),
);
$label = isset($labels[$this->status]) ? $labels[$this->status] : '';
$statustype = ($this->status == self::STATUS_DONE) ? 'status4' : 'status0';
return dolGetStatus($label, $label, '', $statustype, $mode);
}
}