false, 'qrCodeHeight' => 75, 'qrCodeWidth' => 75, 'version' => -1, 'quietzoneSize' => 1 ]); $Epi = new Epirent(); $result = $Epi->requestEpiApi('/v1/packingnote/open?isco=False&cl=' . Epirent_Mandant); $data_output = json_decode($result)->payload; /** ---------- Helpers & Marking (analog Checkout) ---------- */ const APP_TZ = 'Europe/Berlin'; function dt(?string $s): ?DateTimeImmutable { if (!$s) return null; try { return new DateTimeImmutable($s, new DateTimeZone(APP_TZ)); } catch (Throwable $e) { return null; } } function dayStart(DateTimeImmutable $d): DateTimeImmutable { return $d->setTime(0, 0, 0); } function rowClassForDate(?DateTimeImmutable $markDate, ?DateTimeImmutable $today): string { if (!$markDate || !$today) return ''; if ($markDate == $today) return 'text-dark bg-warning'; if ($markDate < $today) return 'bg-danger'; return ''; } /** * Row-Marking Quelle (Check-In): * 1 = $packingjob->date_end * 2 = $NachbereitungsTimeDetail->date_start * 3 = $RePackagingTimeDetail->date_start * 4 = $PackingNoteDetail->date_redelivery * Fallback: $packingjob->date_end */ function resolveRowMarkDateCheckIn( $packingjob, $NachbereitungsTimeDetail, $RePackagingTimeDetail, $PackingNoteDetail, int $source ): ?DateTimeImmutable { $candidate = null; switch ($source) { case 1: $candidate = dt($packingjob->date_end ?? null); break; case 2: $candidate = dt($NachbereitungsTimeDetail->date_start ?? null); break; case 3: $candidate = dt($RePackagingTimeDetail->date_start ?? null); break; case 4: $candidate = dt($PackingNoteDetail->date_redelivery ?? null); break; default: $candidate = null; break; } if (!$candidate) { $candidate = dt($packingjob->date_end ?? null); } return $candidate ? dayStart($candidate) : null; } function echoMarkedTimeLine(?string $dateStr, ?int $timeSeconds, DateTimeImmutable $today, $ReturnTime): void { if (!$dateStr) return; $d = dt($dateStr); if (!$d) return; $mark = dayStart($d); $cls = rowClassForDate($mark, $today); echo $cls ? "" : ""; echo date_format(new \DateTime($dateStr), 'd.m.Y'); if ($ReturnTime) { echo " " . getTimeFromSeconds((string)$timeSeconds); } echo $cls ? "" : ""; } /** ---------- Sortierung nach Ende ---------- */ if (SortCheckIn == 2) { if (is_array($data_output)) { usort($data_output, function ($a, $b) { $timeEndA = $a->time_end / 1000; $timeEndB = $b->time_end / 1000; $datetimeA = strtotime($a->date_end) + $timeEndA; $datetimeB = strtotime($b->date_end) + $timeEndB; return $datetimeA <=> $datetimeB; }); } else { echo "Daten konnten nicht verarbeitet werden."; } } /** ---------- Tabelle ---------- */ foreach ($data_output as $packingjob) { if ($packingjob->is_archived != true) { // OrderDetails $result = $Epi->requestEpiApi('/v1/order/' . $packingjob->order_pk . '?cl=' . Epirent_Mandant); $orderdetail_output = json_decode($result)->payload[0]; // PackingNote Details $PackingNoteDetailResult = $Epi->requestEpiApi('/v1/packingnote/' . $packingjob->primary_key . '?cl=' . Epirent_Mandant); $PackingNoteDetail = json_decode($PackingNoteDetailResult)->payload[0]; // Zeit-Slots aus dem Schedule $NachbereitungsTimeDetail = null; $RePackagingTimeDetail = null; foreach ($orderdetail_output->order_schedule as $scheduledetail) { if ($scheduledetail->name == Nachbereitung_Zeitvariable) { $NachbereitungsTimeDetail = $scheduledetail; } if ($scheduledetail->name == Rückpacken_Zeitvariable) { $RePackagingTimeDetail = $scheduledetail; } } // --- Row-Marking bestimmen (konfigurierbar, analog Checkout) --- $today = dayStart(new DateTimeImmutable('today', new DateTimeZone(APP_TZ))); $limit = null; if (CheckIn_FutureDays != -1) { $limit = $today->modify('+' . (int)CheckIn_FutureDays . ' day'); } // Override-Flag wie bei Checkout: Dispo-Ende erzwingen $source = CheckIn_UseDispoEndForRowMarking ? 1 : (int)CheckInRowMarkSource; $markDate = resolveRowMarkDateCheckIn( $packingjob, $NachbereitungsTimeDetail, $RePackagingTimeDetail, $PackingNoteDetail, $source ); if (CheckIn_FutureDays == -1 || ($markDate && (!$limit || $markDate <= $limit))) { $trClass = rowClassForDate($markDate, $today); echo $trClass ? "