Compare commits

..

No commits in common. "5bb5756604bd059ce798fa3c7184796d411ee2ce" and "221145736fdfdfda78f5dd2cdeeb3b34958c0b31" have entirely different histories.

9 changed files with 14 additions and 210 deletions

View file

@ -144,18 +144,6 @@ $protocol->fk_commande = !empty($p['orderId']) ? (int) $p['orderId'] : nul
$protocol->date_diag = netdiag_api_timestamp($p['dateDiag'] ?? 0); $protocol->date_diag = netdiag_api_timestamp($p['dateDiag'] ?? 0);
$protocol->fk_user_techniker = (int) $user->id; $protocol->fk_user_techniker = (int) $user->id;
$protocol->standort = isset($p['location']) ? (string) $p['location'] : ''; $protocol->standort = isset($p['location']) ? (string) $p['location'] : '';
// Standort leer? Dann aus der Kundenadresse vorbelegen. Der Techniker tippt
// vor Ort selten etwas ein, im Protokoll stand der Ort deshalb fast immer
// leer — obwohl er in Dolibarr am Kunden hinterlegt ist. Eine vom Techniker
// eingetragene Angabe wird NIE überschrieben.
if (trim($protocol->standort) === '' && !empty($protocol->fk_soc)) {
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
$socTmp = new Societe($db);
if ($socTmp->fetch((int) $protocol->fk_soc) > 0) {
$teile = array_filter(array(trim($socTmp->address), trim($socTmp->zip.' '.$socTmp->town)));
$protocol->standort = substr(implode(', ', $teile), 0, 255);
}
}
$protocol->subnet = isset($p['subnet']) ? (string) $p['subnet'] : ''; $protocol->subnet = isset($p['subnet']) ? (string) $p['subnet'] : '';
$protocol->status = isset($p['status']) ? (int) $p['status'] : NetDiagProtocol::STATUS_DRAFT; $protocol->status = isset($p['status']) ? (int) $p['status'] : NetDiagProtocol::STATUS_DRAFT;
$protocol->note = isset($p['note']) ? (string) $p['note'] : ''; $protocol->note = isset($p['note']) ? (string) $p['note'] : '';

View file

@ -135,24 +135,18 @@ class NetDiagDevice extends CommonObject
*/ */
public function fetchAllByProtocol($fk_protocol) public function fetchAllByProtocol($fk_protocol)
{ {
// Alle Spalten in EINER Abfrage holen. Vorher wurden nur die rowids
// gelesen und je Zeile ein eigenes fetch() abgesetzt — bei 46 Geräten
// also 47 Abfragen statt einer. Die Kartenansicht und der
// PDF-Generator laden diese Liste jeweils komplett.
$result = array(); $result = array();
$sql = "SELECT * FROM ".$this->db->prefix().$this->table_element; $sql = "SELECT rowid FROM ".$this->db->prefix().$this->table_element;
$sql .= " WHERE fk_protocol = ".((int) $fk_protocol); $sql .= " WHERE fk_protocol = ".((int) $fk_protocol);
$sql .= " AND entity IN (".getEntity($this->element).")";
$sql .= " ORDER BY INET_ATON(ip), rowid"; $sql .= " ORDER BY INET_ATON(ip), rowid";
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
while ($obj = $this->db->fetch_object($resql)) { while ($obj = $this->db->fetch_object($resql)) {
$dev = new self($this->db); $dev = new self($this->db);
$dev->setVarsFromFetchObj($obj); if ($dev->fetch((int) $obj->rowid) > 0) {
$dev->id = (int) $obj->rowid;
$result[] = $dev; $result[] = $dev;
} }
$this->db->free($resql); }
} }
return $result; return $result;
} }

View file

@ -128,21 +128,18 @@ class NetDiagMeasurement extends CommonObject
*/ */
public function fetchAllByProtocol($fk_protocol) public function fetchAllByProtocol($fk_protocol)
{ {
// Eine Abfrage statt einer je Messung (siehe NetDiagDevice::fetchAllByProtocol)
$result = array(); $result = array();
$sql = "SELECT * FROM ".$this->db->prefix().$this->table_element; $sql = "SELECT rowid FROM ".$this->db->prefix().$this->table_element;
$sql .= " WHERE fk_protocol = ".((int) $fk_protocol); $sql .= " WHERE fk_protocol = ".((int) $fk_protocol);
$sql .= " AND entity IN (".getEntity($this->element).")";
$sql .= " ORDER BY date_measure, rowid"; $sql .= " ORDER BY date_measure, rowid";
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
while ($obj = $this->db->fetch_object($resql)) { while ($obj = $this->db->fetch_object($resql)) {
$m = new self($this->db); $m = new self($this->db);
$m->setVarsFromFetchObj($obj); if ($m->fetch((int) $obj->rowid) > 0) {
$m->id = (int) $obj->rowid;
$result[] = $m; $result[] = $m;
} }
$this->db->free($resql); }
} }
return $result; return $result;
} }

View file

@ -74,4 +74,3 @@ NetDiagFoundViaPort=Port
NetDiagFoundViaArp=ARP NetDiagFoundViaArp=ARP
NetDiagFoundViaMdns=mDNS NetDiagFoundViaMdns=mDNS
NetDiagLastSeen=Zuletzt gesehen NetDiagLastSeen=Zuletzt gesehen
NetDiagOnlyWithFindings=nur mit Befund

View file

@ -74,4 +74,3 @@ NetDiagFoundViaPort=Port
NetDiagFoundViaArp=ARP NetDiagFoundViaArp=ARP
NetDiagFoundViaMdns=mDNS NetDiagFoundViaMdns=mDNS
NetDiagLastSeen=Last seen NetDiagLastSeen=Last seen
NetDiagOnlyWithFindings=only with findings

View file

@ -344,44 +344,6 @@ function netdiagKundenfelder()
'reachedTarget' => array('Ziel erreicht', ''), 'reachedTarget' => array('Ziel erreicht', ''),
// WLAN // WLAN
'anzahlNetze' => array('Sichtbare WLAN-Netze', ''), 'anzahlNetze' => array('Sichtbare WLAN-Netze', ''),
// --- Schlüssel, welche die App TATSÄCHLICH liefert ---
// Sie weichen teils von den obigen ab (deutsche Namen, andere Schreibung).
// Ohne diese Einträge verwirft die Whitelist sie stillschweigend und im
// Kundendokument steht bei Portscan, Traceroute, iPerf, SNMP und
// IP-Konflikt nur noch die Ampel — ohne einen einzigen Messwert. Genau
// das ist beim ersten Bau dieser Tabelle passiert, weil sie nur gegen
// selbst erzeugte Testdaten geprüft wurde statt gegen die echten
// Werkzeuge. Beim Anlegen eines Werkzeugs hier eintragen.
'ziel' => array('Ziel', ''),
'zielErreicht' => array('Ziel erreicht', ''),
'hops' => array('Zwischenstellen', ''),
'gegenstelle' => array('Gegenstelle', ''),
'downloadMbps' => array('Download', 'Mbit/s'),
'uploadMbps' => array('Upload', 'Mbit/s'),
'ip' => array('Gerät', ''),
'scanned' => array('Geprüfte Ports', ''),
'open' => array('Offene Ports', ''),
'geprueft' => array('Geprüfte Adressen', ''),
'runden' => array('Messrunden', ''),
'konflikte' => array('IP-Konflikte', ''),
'port' => array('Switch-Port', ''),
'linkSpeed' => array('Verbindungsgeschwindigkeit', ''),
'eingangsFehler' => array('Fehler eingehend', ''),
'ausgangsFehler' => array('Fehler ausgehend', ''),
// IP-Test (Dose): die Seite reicht das LinkInfo-Objekt durch
'ipv4' => array('IP-Adresse', ''),
'prefixLength' => array('Präfixlänge', ''),
'dhcpServer' => array('DHCP-Server', ''),
'leaseSec' => array('Lease-Dauer', 's'),
'linkSpeedMbps' => array('Verbindungsgeschwindigkeit', 'Mbit/s'),
'rxLinkSpeedMbps' => array('Empfangsgeschwindigkeit', 'Mbit/s'),
'ssid' => array('WLAN-Name', ''),
'raum' => array('Raum / Dose', ''),
'iface' => array('Schnittstelle', ''),
'typ' => array('Anschlussart', ''),
'neu' => array('Neu hinzugekommen', ''),
'nichtMehrErreichbar' => array('Nicht mehr erreichbar', ''),
'demodaten' => array('DEMODATEN — keine echte Messung', ''),
// Fehler/Hinweise — immer zeigen, sonst bliebe eine gelbe oder rote Ampel // Fehler/Hinweise — immer zeigen, sonst bliebe eine gelbe oder rote Ampel
// im Kundendokument ohne jede Erklärung stehen. Der Text läuft durch // im Kundendokument ohne jede Erklärung stehen. Der Text läuft durch
// netdiagKundentext() und wird dort von Messgeräte-Interna befreit. // netdiagKundentext() und wird dort von Messgeräte-Interna befreit.
@ -468,82 +430,3 @@ function netdiagKundentext($text)
} }
return $text; return $text;
} }
/**
* Klarname eines Werkzeugs für die Anzeige.
*
* Die kanonischen Namen stehen eigentlich in der App (`Tool.name`), das
* Dolibarr-Modul kann darauf aber nicht zugreifen. Deshalb hier eine bewusst
* kurze Zuordnung statt eines zweiten Satzes Sprachschlüssel mit Rückfall
* auf die ID, damit ein neues Werkzeug nie einen leeren Titel bekommt.
*
* Enthält auch Werkzeuge, die es in der App nicht mehr gibt („dhcpcheck",
* „wifiscan"): in der Produktionsdatenbank stehen dazu noch Messungen aus
* älteren Protokollen, und die sollen weiterhin lesbar sein.
*
* @param string $tool Werkzeug-ID aus der Messung
* @return string Klarname, oder die ID selbst wenn unbekannt
*/
function netdiagToolName($tool)
{
$map = array(
'ipscan' => 'IP-Scanner',
'portscan' => 'Port-Scan',
'ping' => 'Ping / Qualität',
'ipconflict' => 'IP-Konflikt',
'snmp' => 'SNMP-Switch',
'traceroute' => 'Traceroute',
'stresstest' => 'Dauer-/Stresstest',
'iperf' => 'Durchsatz-Test',
'wifikanal' => 'WLAN-Kanalanalyse',
'monitor' => 'Geräte-Monitor',
'iptest' => 'IP-Test (Dose)',
'wifitrack' => 'WLAN-Empfang',
// nicht mehr vorhandene Werkzeuge, aber in Altprotokollen enthalten
'dhcpcheck' => 'DHCP-Prüfung',
'wifiscan' => 'WLAN-Scan',
);
return $map[$tool] ?? $tool;
}
/**
* Messparameter für die Anzeige aufbereiten („Ziel: 192.168.1.1").
*
* Ohne sie steht im Protokoll zwar das Ergebnis, aber nicht, worauf es sich
* bezieht bei Prod-Messung #126 war deshalb nicht erkennbar, gegen welches
* Ziel der Dauertest lief. Nur ausgefüllte Parameter erscheinen.
*
* @param string $json JSON-String der Parameter
* @return string lesbarer Text, leer wenn nichts anzuzeigen ist
*/
function netdiagFormatParams($json)
{
if (empty($json)) {
return '';
}
$data = json_decode($json, true);
if (!is_array($data) || empty($data)) {
return '';
}
$labels = array(
'host' => 'Ziel',
'subnet' => 'Netzbereich',
'ip' => 'Gerät',
'ports' => 'Ports',
'port' => 'Port',
'count' => 'Anzahl Proben',
'durationSec' => 'Dauer (s)',
'intervalSec' => 'Messabstand (s)',
'community' => 'SNMP-Community',
'rounds' => 'Runden',
'timeoutMs' => 'Zeitgrenze (ms)',
);
$teile = array();
foreach ($data as $k => $v) {
if ($v === null || $v === '' || is_array($v)) {
continue;
}
$teile[] = ($labels[$k] ?? ucfirst((string) $k)).': '.$v;
}
return implode(' · ', $teile);
}

View file

@ -181,19 +181,10 @@ function netdiagGeneratePdf($db, $protocol, $outputlangs)
// wie ein abgebrochenes Dokument. // wie ein abgebrochenes Dokument.
netdiagPdfEnsureSpace($pdf, 11); netdiagPdfEnsureSpace($pdf, 11);
$pdf->SetFont('', 'B', 9); $pdf->SetFont('', 'B', 9);
// Klarname statt interner ID — „ipscan" sagt dem Kunden nichts $title = ($m->category ? '['.$m->category.'] ' : '').$m->tool.($m->label ? ' — '.$m->label : '');
$title = netdiagToolName($m->tool).($m->label ? ' — '.$m->label : '');
$pdf->Cell(150, 6, dol_trunc($title, 80), 1, 0, 'L'); $pdf->Cell(150, 6, dol_trunc($title, 80), 1, 0, 'L');
$pdf->Cell(30, 6, $statusmarks[$st].$statuslabels[$st], 1, 1, 'C', true); $pdf->Cell(30, 6, $statusmarks[$st].$statuslabels[$st], 1, 1, 'C', true);
$pdf->SetFont('', '', 8); $pdf->SetFont('', '', 8);
// Messparameter: ohne sie steht das Ergebnis ohne Bezug da — man sieht
// nicht, gegen welches Ziel gemessen wurde (Prod-Messung #126).
$params = netdiagFormatParams($m->params);
if ($params !== '') {
$pdf->SetFont('', 'I', 7);
$pdf->MultiCell(180, 4, $params, 1, 'L');
$pdf->SetFont('', '', 8);
}
if ($m->tool === 'stresstest') { if ($m->tool === 'stresstest') {
netdiagPdfStressTest($pdf, $m->result); netdiagPdfStressTest($pdf, $m->result);
} elseif ($m->tool === 'wifikanal') { } elseif ($m->tool === 'wifikanal') {

View file

@ -67,10 +67,6 @@ if (!$user->hasRight('netdiag', 'protocol', 'read')) {
$search_ref = GETPOST('search_ref', 'alpha'); $search_ref = GETPOST('search_ref', 'alpha');
$search_soc = GETPOST('search_soc', 'alpha'); $search_soc = GETPOST('search_soc', 'alpha');
// „nur mit Befund": zeigt Protokolle, in denen mindestens eine Messung
// Warnung oder Fehler ist — beim Durchsehen vieler Protokolle die eigentliche
// Frage („wo muss ich nochmal ran?")
$search_problem = GETPOST('search_problem', 'int');
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
$page = GETPOSTINT('page'); $page = GETPOSTINT('page');
if ($page < 0) { if ($page < 0) {
@ -89,16 +85,7 @@ llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-netdiag page-list');
// Datensätze laden // Datensätze laden
$sql = "SELECT p.rowid, p.ref, p.label, p.date_diag, p.standort, p.subnet, p.status,"; $sql = "SELECT p.rowid, p.ref, p.label, p.date_diag, p.standort, p.subnet, p.status,";
$sql .= " s.rowid as socid, s.nom as socname,"; $sql .= " s.rowid as socid, s.nom as socname,";
$sql .= " (SELECT COUNT(*) FROM ".$db->prefix()."netdiag_device d WHERE d.fk_protocol = p.rowid) as devcount,"; $sql .= " (SELECT COUNT(*) FROM ".$db->prefix()."netdiag_device d WHERE d.fk_protocol = p.rowid) as devcount";
// Schlechteste Einzelmessung als Protokoll-Ampel. Status 3 („nicht messbar")
// darf dabei NICHT als schlechtester Wert gelten — er ist keine Aussage über
// das Kundennetz; deshalb wird er separat gezählt statt in MAX() einzugehen.
$sql .= " (SELECT MAX(m.measure_status) FROM ".$db->prefix()."netdiag_measurement m
WHERE m.fk_protocol = p.rowid AND m.measure_status IN (0,1,2)) as worststatus,";
$sql .= " (SELECT COUNT(*) FROM ".$db->prefix()."netdiag_measurement m
WHERE m.fk_protocol = p.rowid) as meascount,";
$sql .= " (SELECT COUNT(*) FROM ".$db->prefix()."netdiag_measurement m
WHERE m.fk_protocol = p.rowid AND m.measure_status = 3) as unmesscount";
$sql .= " FROM ".$db->prefix()."netdiag_protocol as p"; $sql .= " FROM ".$db->prefix()."netdiag_protocol as p";
$sql .= " LEFT JOIN ".$db->prefix()."societe as s ON s.rowid = p.fk_soc"; $sql .= " LEFT JOIN ".$db->prefix()."societe as s ON s.rowid = p.fk_soc";
$sql .= " WHERE p.entity IN (".getEntity('netdiagprotocol').")"; $sql .= " WHERE p.entity IN (".getEntity('netdiagprotocol').")";
@ -108,10 +95,6 @@ if ($search_ref) {
if ($search_soc) { if ($search_soc) {
$sql .= natural_search('s.nom', $search_soc); $sql .= natural_search('s.nom', $search_soc);
} }
if ($search_problem) {
$sql .= " AND EXISTS (SELECT 1 FROM ".$db->prefix()."netdiag_measurement m2
WHERE m2.fk_protocol = p.rowid AND m2.measure_status IN (1,2))";
}
$sql .= " ORDER BY p.date_diag DESC, p.rowid DESC"; $sql .= " ORDER BY p.date_diag DESC, p.rowid DESC";
$sql .= $db->plimit($limit, $offset); $sql .= $db->plimit($limit, $offset);
@ -133,8 +116,7 @@ print '<table class="tagtable liste">';
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print '<td><input type="text" name="search_ref" class="maxwidth100" value="'.dol_escape_htmltag($search_ref).'" placeholder="'.$langs->trans("Ref").'"></td>'; print '<td><input type="text" name="search_ref" class="maxwidth100" value="'.dol_escape_htmltag($search_ref).'" placeholder="'.$langs->trans("Ref").'"></td>';
print '<td><input type="text" name="search_soc" class="maxwidth150" value="'.dol_escape_htmltag($search_soc).'" placeholder="'.$langs->trans("ThirdParty").'"></td>'; print '<td><input type="text" name="search_soc" class="maxwidth150" value="'.dol_escape_htmltag($search_soc).'" placeholder="'.$langs->trans("ThirdParty").'"></td>';
print '<td colspan="3" class="right"><label class="opacitymedium small"><input type="checkbox" name="search_problem" value="1"'.($search_problem ? ' checked' : '').'> '.$langs->trans("NetDiagOnlyWithFindings").'</label></td>'; print '<td colspan="4" class="right"><input type="submit" class="button small" value="'.$langs->trans("Search").'"></td>';
print '<td class="right"><input type="submit" class="button small" value="'.$langs->trans("Search").'"></td>';
print '</tr>'; print '</tr>';
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
@ -143,7 +125,6 @@ print '<th>'.$langs->trans("ThirdParty").'</th>';
print '<th>'.$langs->trans("DateDiag").'</th>'; print '<th>'.$langs->trans("DateDiag").'</th>';
print '<th>'.$langs->trans("Location").'</th>'; print '<th>'.$langs->trans("Location").'</th>';
print '<th class="right">'.$langs->trans("NetDiagDevices").'</th>'; print '<th class="right">'.$langs->trans("NetDiagDevices").'</th>';
print '<th class="center">'.$langs->trans("NetDiagMeasurements").'</th>';
print '<th class="center">'.$langs->trans("Status").'</th>'; print '<th class="center">'.$langs->trans("Status").'</th>';
print '</tr>'; print '</tr>';
@ -162,33 +143,11 @@ foreach ($rows as $obj) {
print '<td>'.dol_print_date($db->jdate($obj->date_diag), 'dayhour').'</td>'; print '<td>'.dol_print_date($db->jdate($obj->date_diag), 'dayhour').'</td>';
print '<td>'.dol_escape_htmltag($obj->standort).'</td>'; print '<td>'.dol_escape_htmltag($obj->standort).'</td>';
print '<td class="right">'.((int) $obj->devcount).'</td>'; print '<td class="right">'.((int) $obj->devcount).'</td>';
// Messungs-Ampel: schlechteste Einzelmessung, plus Hinweis auf nicht
// messbare Punkte. So sieht man in der Liste, wo noch etwas zu tun ist,
// ohne jedes Protokoll einzeln zu öffnen.
print '<td class="center">';
$meascount = (int) $obj->meascount;
if ($meascount === 0) {
print '<span class="opacitymedium">-</span>';
} else {
$worst = ($obj->worststatus === null) ? 3 : (int) $obj->worststatus;
if ($worst < 0 || $worst > 3) {
$worst = 1;
}
$ampellabels = array(0 => 'NetDiagMeasureOk', 1 => 'NetDiagMeasureWarn', 2 => 'NetDiagMeasureFail', 3 => 'NetDiagMeasureUnmeasurable');
$ampelcss = array(0 => 'badge-status4', 1 => 'badge-status1', 2 => 'badge-status8', 3 => 'badge-status0');
print '<span class="badge '.$ampelcss[$worst].'">'.$langs->trans($ampellabels[$worst]).'</span>';
print ' <span class="opacitymedium small">'.$meascount;
if ((int) $obj->unmesscount > 0) {
print ', '.((int) $obj->unmesscount).' n.m.';
}
print '</span>';
}
print '</td>';
print '<td class="center">'.$proto->getLibStatut(3).'</td>'; print '<td class="center">'.$proto->getLibStatut(3).'</td>';
print '</tr>'; print '</tr>';
} }
if (empty($rows)) { if (empty($rows)) {
print '<tr><td colspan="7" class="opacitymedium center">'.$langs->trans("NoRecordFound").'</td></tr>'; print '<tr><td colspan="6" class="opacitymedium center">'.$langs->trans("NoRecordFound").'</td></tr>';
} }
print '</table>'; print '</table>';

View file

@ -260,14 +260,8 @@ foreach ($measurements as $m) {
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td class="nowraponall">'.dol_print_date($m->date_measure, 'dayhour').'</td>'; print '<td class="nowraponall">'.dol_print_date($m->date_measure, 'dayhour').'</td>';
print '<td>'.dol_escape_htmltag($m->category).'</td>'; print '<td>'.dol_escape_htmltag($m->category).'</td>';
print '<td>'.dol_escape_htmltag(netdiagToolName($m->tool)).'</td>'; print '<td>'.dol_escape_htmltag($m->tool).'</td>';
print '<td>'.dol_escape_htmltag($m->label); print '<td>'.dol_escape_htmltag($m->label).'</td>';
// Messparameter darunter: sonst ist nicht erkennbar, wogegen gemessen wurde
$params = netdiagFormatParams($m->params);
if ($params !== '') {
print '<br><span class="opacitymedium small">'.dol_escape_htmltag($params).'</span>';
}
print '</td>';
print '<td>'.netdiagFormatResult($m->result, $m->tool).'</td>'; print '<td>'.netdiagFormatResult($m->result, $m->tool).'</td>';
print '<td class="center"><span class="badge '.$statuscss[$st].'">'.$langs->trans($statuslabels[$st]).'</span></td>'; print '<td class="center"><span class="badge '.$statuscss[$st].'">'.$langs->trans($statuslabels[$st]).'</span></td>';
print '</tr>'; print '</tr>';