From 23b1768be74d0b59555b7d593b35479fec0a89df Mon Sep 17 00:00:00 2001 From: Leopold Strobl Date: Mon, 22 Jun 2026 13:03:26 +0200 Subject: [PATCH] =?UTF-8?q?Jahresfilterung=20f=C3=BCr=20ROI=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- dist/ROI.php | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 795ee96..de75622 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ config.php .vscode -sftp.json \ No newline at end of file +sftp.json +.claude \ No newline at end of file diff --git a/dist/ROI.php b/dist/ROI.php index 7cc548f..4ee81de 100644 --- a/dist/ROI.php +++ b/dist/ROI.php @@ -16,6 +16,26 @@ use PhpOffice\PhpSpreadsheet\Cell\DataType; $Epi = new Epirent(); +/* ========================= + Filter (Jahres-Range) + – ROI wird nur ausgeführt, wenn der User einen Zeitraum gewählt hat + oder explizit "Alles" anfordert. Das spart bei großen Datenbeständen + teure API-Calls. + ========================= */ +$filterMode = strtolower((string)($_GET['mode'] ?? '')); +$filterFrom = isset($_GET['from']) ? (int)$_GET['from'] : 0; +$filterTo = isset($_GET['to']) ? (int)$_GET['to'] : 0; + +if ($filterFrom > 0 && $filterTo > 0 && $filterTo < $filterFrom) { + [$filterFrom, $filterTo] = [$filterTo, $filterFrom]; +} + +$computeRoi = in_array($filterMode, ['range', 'all'], true); +if ($filterMode === 'range' && ($filterFrom <= 0 || $filterTo <= 0)) { + $computeRoi = false; + $filterMode = ''; +} + /* ========================= Helpers ========================= */ @@ -706,6 +726,14 @@ function processLineItem( 1) Invoices holen + Daten sammeln ========================= */ +// Defaults für die HTML-Ausgabe, wenn keine Berechnung läuft +$years = []; +$pivotRows = []; +$excelFileName = ''; +$excelDownloadUrl = ''; + +if ($computeRoi) { + $slotItemsDirect = []; // productPk => list of intervals $slotItemsIncl = []; // productPk => list of intervals @@ -716,6 +744,15 @@ foreach ($invoiceList as $inv) { $invoicePk = (int)($inv->primary_key ?? 0); if ($invoicePk <= 0) continue; + // Vorab-Filter: wenn das Listen-Item bereits invoice_date hat, sparen wir den teuren Detail-Call + if ($filterMode === 'range') { + $listYear = yearFromDate((string)($inv->invoice_date ?? '')) ?? 0; + if ($listYear > 0) { + if ($filterFrom > 0 && $listYear < $filterFrom) continue; + if ($filterTo > 0 && $listYear > $filterTo) continue; + } + } + $invRes = apiJsonDecode($Epi->requestEpiApi('/v1/invoice/' . $invoicePk . '?cl=' . Epirent_Mandant)); $invObj = ($invRes && ($invRes->success ?? false) && !empty($invRes->payload[0])) ? $invRes->payload[0] : null; if (!$invObj) continue; @@ -725,6 +762,13 @@ foreach ($invoiceList as $inv) { $invoiceNo = (int)($invObj->invoice_no ?? 0); $orderPk = (int)($invObj->order_pk ?? 0); + // Endgültiger Year-Filter (falls Listen-Antwort kein Datum hatte) + if ($filterMode === 'range') { + if ($invoiceYear <= 0) continue; + if ($filterFrom > 0 && $invoiceYear < $filterFrom) continue; + if ($filterTo > 0 && $invoiceYear > $filterTo) continue; + } + // Storno-Erkennung (Credit Note): sum_net < 0 $invoiceIsCredit = ((float)($invObj->sum_net ?? 0.0)) < 0.0; @@ -966,6 +1010,8 @@ $sheet->freezePane("A" . ($headerRow + 1)); $writer = new Xlsx($spreadsheet); $writer->save($excelFilePath); +} // end if ($computeRoi) + /* ========================= 5) HTML Ausgabe ========================= */ @@ -1035,6 +1081,49 @@ function slotsToDisplay(array $slotMap): array { + +
+
Zeitraum wählen
+
+
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+ + +
Aktuell:  –  + +
Aktuell: alle Jahre + +
+
+
+ + +
+ Bitte oben einen Zeitraum auswählen und auf Zeitraum berechnen klicken, + oder Alles berechnen für die vollständige Auswertung. +
+ +
Pivot: Artikel × Rechnungsjahr
@@ -1224,6 +1313,8 @@ function slotsToDisplay(array $slotMap): array {
+ +