Compare commits
2 commits
9f07896b05
...
36dd18f53a
| Author | SHA1 | Date | |
|---|---|---|---|
| 36dd18f53a | |||
| 90cbee6e81 |
4 changed files with 172 additions and 2 deletions
34
ChangeLog.md
34
ChangeLog.md
|
|
@ -1,5 +1,39 @@
|
|||
# Changelog NetDiag
|
||||
|
||||
## 1.1.2 — 2026-08-16
|
||||
|
||||
### Geräte-Monitor bekommt einen eigenen PDF-Zweig
|
||||
|
||||
Die Dauerüberwachung lief bisher in den generischen `else`-Zweig von
|
||||
`netdiag_pdf.lib.php` und wurde von `netdiagPdfFlattenResult()` zu **einer**
|
||||
`|`-getrennten Zeile zusammengeschoben. Bei zehn überwachten Geräten standen
|
||||
damit die zehn Geräte-Zeilen UND sämtliche Einzelausfälle in einer einzigen
|
||||
Tabellenzelle — vollständig, aber beim Kunden nicht lesbar. Dauertest und
|
||||
WLAN-Kanal hatten längst je einen Tabellen-Renderer, der Monitor nicht.
|
||||
|
||||
- **`netdiagPdfMonitor()`**: Kennzahlenzeile, Tabelle „Überwachte Geräte",
|
||||
Tabelle „Einzelne Ausfälle" mit Uhrzeiten, Hinweis zum Messverfahren am Ende.
|
||||
- **Die Falle dabei**, gegen die es einen Kommentar im Code gibt: beim Dauertest
|
||||
führt ein gesetztes `hinweis` zum sofortigen Abbruch der Ausgabe. Der Monitor
|
||||
legt aber IMMER einen Hinweis an (das Messverfahren gehört zur Aussage dazu) —
|
||||
derselbe Aufbau hätte hier bei **jedem** Lauf alle Zahlen verschluckt. Nur
|
||||
`fehler` bricht ab, der Hinweis steht am Schluss.
|
||||
- Tabellenköpfe wiederholen sich nach einem Seitenumbruch („— Fortsetzung"),
|
||||
wie in der Geräteliste.
|
||||
- Obergrenze 200 Ausfallzeilen gegen den pathologischen Fall (ein im
|
||||
Sekundentakt flappendes Gerät erzeugt über einen Arbeitstag vierstellig viele
|
||||
Segmente). Gekürzt wird **sichtbar**: „… und N weitere Ausfälle" steht im
|
||||
Dokument, sonst läse sich das Protokoll als vollständig.
|
||||
- **`ausfallzeitSek` heißt jetzt „Ausfallzeit (schlechtestes Gerät)"** — der
|
||||
Wert ist der des schlechtesten Geräts, nicht die Summe über alle. Bei zehn
|
||||
überwachten Geräten las sich „Ausfallzeit: 8 min" wie eine Gesamtaussage.
|
||||
Gleiche Korrektur in `app/src/lib/messfelder.ts`, damit App und PDF dasselbe
|
||||
Feld gleich benennen.
|
||||
|
||||
Geprüft gegen die lokale Testinstanz mit vier konstruierten Fällen (10 Geräte
|
||||
mit Aussetzern, ein durchgehend totes Gerät, 250 Einzelausfälle über sechs
|
||||
Seiten, abgerissener Lauf) und gegen die echte Monitor-Messung aus ND2026-0016.
|
||||
|
||||
## 1.1.1 — 2026-08-16
|
||||
|
||||
### Vier stille Fehler im Kundendokument und im Sync
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class modNetDiag extends DolibarrModules
|
|||
$this->editor_url = '';
|
||||
$this->editor_squarred_logo = '';
|
||||
|
||||
$this->version = '1.1.1';
|
||||
$this->version = '1.1.2';
|
||||
|
||||
// Konstanten-Name in llx_const für Modul-Status
|
||||
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
|
||||
|
|
|
|||
|
|
@ -338,7 +338,10 @@ function netdiagKundenfelder()
|
|||
// vollständig ins Kundendokument, nicht nur die Ampel.
|
||||
'geraeteAnzahl' => array('Überwachte Geräte', ''),
|
||||
'verfuegbarkeitProzent' => array('Verfügbarkeit (schlechtestes Gerät)', '%'),
|
||||
'ausfallzeitSek' => array('Ausfallzeit', 's'),
|
||||
// „Ausfallzeit" allein war irreführend: der Wert ist der des schlechtesten
|
||||
// Geräts, nicht die Summe über alle. Bei zehn überwachten Geräten liest
|
||||
// sich „Ausfallzeit: 8 min" sonst wie eine Gesamtaussage.
|
||||
'ausfallzeitSek' => array('Ausfallzeit (schlechtestes Gerät)', 's'),
|
||||
'aussetzer' => array('Aussetzer', ''),
|
||||
'geraete' => array('Je Gerät', ''),
|
||||
'ausfaelle' => array('Einzelne Ausfälle', ''),
|
||||
|
|
|
|||
|
|
@ -198,6 +198,8 @@ function netdiagGeneratePdf($db, $protocol, $outputlangs)
|
|||
netdiagPdfStressTest($pdf, $m->result);
|
||||
} elseif ($m->tool === 'wifikanal') {
|
||||
netdiagPdfWifiKanal($pdf, $m->result);
|
||||
} elseif ($m->tool === 'monitor') {
|
||||
netdiagPdfMonitor($pdf, $m->result);
|
||||
} else {
|
||||
$pdf->MultiCell(180, 5, netdiagPdfFlattenResult($m->result), 1, 'L');
|
||||
}
|
||||
|
|
@ -371,6 +373,137 @@ function netdiagPdfStressTest($pdf, $json)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Geräte-Dauerüberwachung strukturiert ins PDF schreiben.
|
||||
*
|
||||
* Dritter eigener Zweig neben Dauertest und WLAN-Kanal, aus demselben Grund:
|
||||
* `netdiagPdfFlattenResult()` schiebt alles zu EINER `|`-getrennten Zeile
|
||||
* zusammen. Bei zehn überwachten Geräten standen damit die zehn Zeilen aus
|
||||
* `geraete` UND sämtliche Einzelausfälle in einer einzigen Tabellenzelle —
|
||||
* vollständig, aber beim Kunden nicht lesbar.
|
||||
*
|
||||
* ACHTUNG, Unterschied zu netdiagPdfStressTest(): dort führt ein gesetztes
|
||||
* `hinweis` zum sofortigen Abbruch. Hier darf es das NICHT — der Monitor legt
|
||||
* IMMER einen Hinweis an (das Messverfahren gehört zur Aussage dazu, siehe
|
||||
* `buildMonitorMeasurement()` in app/src/lib/monitor.ts). Ein Frühabbruch
|
||||
* würde also bei jedem Monitor-Lauf sämtliche Zahlen verschlucken. Der Hinweis
|
||||
* steht deshalb am Ende, nur `fehler` bricht ab.
|
||||
*
|
||||
* @param TCPDF $pdf PDF-Objekt (Cursor steht direkt hinter der Titelzeile)
|
||||
* @param string $json result-JSON der Messung
|
||||
* @return void
|
||||
*/
|
||||
function netdiagPdfMonitor($pdf, $json)
|
||||
{
|
||||
$data = json_decode((string) $json, true);
|
||||
if (!is_array($data)) {
|
||||
$pdf->MultiCell(180, 5, netdiagPdfFlattenResult($json), 1, 'L');
|
||||
return;
|
||||
}
|
||||
if (!empty($data['fehler']) || !empty($data['error'])) {
|
||||
$pdf->MultiCell(180, 5, netdiagKundentext((string) ($data['fehler'] ?? $data['error'])), 1, 'L');
|
||||
return;
|
||||
}
|
||||
|
||||
// Kennzahlenzeile. Bezeichnungen bewusst wie in netdiagKundenfelder(),
|
||||
// damit dasselbe Feld im PDF und in der Dolibarr-Ansicht gleich heißt.
|
||||
$sum = array();
|
||||
if (isset($data['dauerSekunden'])) {
|
||||
$sum[] = 'Messdauer: '.netdiagDauerLesbar($data['dauerSekunden']);
|
||||
}
|
||||
if (isset($data['intervallSek'])) {
|
||||
$sum[] = 'Messabstand: '.$data['intervallSek'].' s';
|
||||
}
|
||||
if (isset($data['geraeteAnzahl'])) {
|
||||
$sum[] = 'Überwachte Geräte: '.$data['geraeteAnzahl'];
|
||||
}
|
||||
if (isset($data['verfuegbarkeitProzent']) && $data['verfuegbarkeitProzent'] !== null) {
|
||||
$sum[] = 'Verfügbarkeit (schlechtestes Gerät): '.number_format((float) $data['verfuegbarkeitProzent'], 1, ',', '').' %';
|
||||
}
|
||||
if (isset($data['aussetzer'])) {
|
||||
$sum[] = 'Aussetzer: '.$data['aussetzer'];
|
||||
}
|
||||
if (!empty($data['ausfallzeitSek'])) {
|
||||
$sum[] = 'Ausfallzeit (schlechtestes Gerät): '.netdiagDauerLesbar($data['ausfallzeitSek']);
|
||||
}
|
||||
if (!empty($data['laengsterAusfallSek'])) {
|
||||
$sum[] = 'Längster Ausfall: '.netdiagDauerLesbar($data['laengsterAusfallSek']);
|
||||
}
|
||||
if (!empty($sum)) {
|
||||
$pdf->MultiCell(180, 5, implode(' | ', $sum), 1, 'L');
|
||||
}
|
||||
|
||||
// Je Gerät eine eigene Zeile — das ist der eigentliche Beleg. Die Zeilen
|
||||
// kommen vorformatiert aus der App (dieselben, die dort in der Messungs-
|
||||
// liste stehen), wie beim Dauertest: eine Quelle der Wahrheit.
|
||||
$geraete = (isset($data['geraete']) && is_array($data['geraete'])) ? $data['geraete'] : array();
|
||||
if (!empty($geraete)) {
|
||||
netdiagPdfEnsureSpace($pdf, 10);
|
||||
$pdf->SetFont('', 'B', 8);
|
||||
$pdf->Cell(180, 5, 'Überwachte Geräte ('.count($geraete).')', 1, 1, 'L');
|
||||
$pdf->SetFont('', '', 8);
|
||||
foreach ($geraete as $line) {
|
||||
netdiagPdfEnsureSpace($pdf, 5, function ($p) use ($geraete) {
|
||||
$p->SetFont('', 'B', 8);
|
||||
$p->Cell(180, 5, 'Überwachte Geräte ('.count($geraete).') — Fortsetzung', 1, 1, 'L');
|
||||
$p->SetFont('', '', 8);
|
||||
});
|
||||
$pdf->Cell(180, 5, dol_trunc((string) $line, 120), 1, 1, 'L');
|
||||
}
|
||||
}
|
||||
|
||||
// Einzelne Ausfälle mit Uhrzeit. Genau das ist der Nachweis bei der
|
||||
// häufigsten Reklamation („die Kamera fällt ständig aus").
|
||||
$ausfaelle = (isset($data['ausfaelle']) && is_array($data['ausfaelle'])) ? $data['ausfaelle'] : array();
|
||||
netdiagPdfEnsureSpace($pdf, 10);
|
||||
if (empty($ausfaelle)) {
|
||||
$pdf->SetFont('', 'I', 8);
|
||||
$pdf->Cell(180, 5, 'Kein Ausfall während der Überwachung.', 1, 1, 'L');
|
||||
$pdf->SetFont('', '', 8);
|
||||
} else {
|
||||
$pdf->SetFont('', 'B', 8);
|
||||
$pdf->Cell(180, 5, 'Einzelne Ausfälle ('.count($ausfaelle).')', 1, 1, 'L');
|
||||
$pdf->SetFont('', '', 8);
|
||||
/*
|
||||
* Obergrenze gegen den pathologischen Fall: ein im Sekundentakt
|
||||
* flappendes Gerät erzeugt über einen Arbeitstag vierstellig viele
|
||||
* Segmente — das wären zweistellig viele Seiten reine Ausfallliste.
|
||||
* 200 Zeilen sind rund vier Seiten und belegen jede reale Störung
|
||||
* ausreichend. Gekürzt wird NICHT stillschweigend: die Restzahl steht
|
||||
* sichtbar im Dokument, sonst läse sich das Protokoll als vollständig.
|
||||
*/
|
||||
$max = 200;
|
||||
$i = 0;
|
||||
foreach ($ausfaelle as $line) {
|
||||
if ($i >= $max) {
|
||||
break;
|
||||
}
|
||||
netdiagPdfEnsureSpace($pdf, 5, function ($p) use ($ausfaelle) {
|
||||
$p->SetFont('', 'B', 8);
|
||||
$p->Cell(180, 5, 'Einzelne Ausfälle ('.count($ausfaelle).') — Fortsetzung', 1, 1, 'L');
|
||||
$p->SetFont('', '', 8);
|
||||
});
|
||||
$pdf->Cell(180, 5, dol_trunc((string) $line, 120), 1, 1, 'L');
|
||||
$i++;
|
||||
}
|
||||
$rest = count($ausfaelle) - $max;
|
||||
if ($rest > 0) {
|
||||
netdiagPdfEnsureSpace($pdf, 5);
|
||||
$pdf->SetFont('', 'I', 8);
|
||||
$pdf->Cell(180, 5, '… und '.$rest.' weitere Ausfälle, hier aus Platzgründen nicht einzeln aufgeführt.', 1, 1, 'L');
|
||||
$pdf->SetFont('', '', 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Hinweis zum Schluss: Messverfahren und ggf. abgerissener Lauf.
|
||||
if (!empty($data['hinweis'])) {
|
||||
netdiagPdfEnsureSpace($pdf, 10);
|
||||
$pdf->SetFont('', 'I', 7);
|
||||
$pdf->MultiCell(180, 4, netdiagKundentext((string) $data['hinweis']), 1, 'L');
|
||||
$pdf->SetFont('', '', 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WLAN-Kanal-Momentaufnahme im PDF als Tabelle ausgeben.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue