All checks were successful
Deploy netdiag / deploy (push) Successful in 14s
protocols.php (POST) gab bei JEDEM Sync HTTP 500 zurueck — 0 Protokolle wurden je gespeichert. Ursache: protocol/device/measurement-Klassen deklarierten das tms-Feld im $fields-Array als 'notnull' => 1. Dolibarrs createCommon() bricht ab (-1), wenn ein notnull-Feld den Wert NULL hat und kein 'default' gesetzt ist. tms wird von der App nie gesetzt (die DB fuellt es per CURRENT_TIMESTAMP), also schlug jedes Insert fehl, bevor es ueberhaupt an die DB ging. Fix: tms auf 'notnull' => 0 — so wie es der Dolibarr-Modul-Builder auch generiert. Die DB-Spalte bleibt NOT NULL DEFAULT CURRENT_TIMESTAMP. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
233 lines
8.5 KiB
PHP
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' => 0, '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);
|
|
}
|
|
}
|