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, $DispoTimeDetail, 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; case 5: $candidate = dt($DispoTimeDetail->date_end ?? 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; $DispoTimeDetail = null; foreach ($orderdetail_output->order_schedule as $scheduledetail) { if ($scheduledetail->name == Nachbereitung_Zeitvariable) { $NachbereitungsTimeDetail = $scheduledetail; } if ($scheduledetail->name == Rückpacken_Zeitvariable) { $RePackagingTimeDetail = $scheduledetail; } if ($scheduledetail->name == "Dispo") { $DispoTimeDetail = $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, $DispoTimeDetail, $source ); if (CheckIn_FutureDays == -1 || ($markDate && (!$limit || $markDate <= $limit))) { $trClass = rowClassForDate($markDate, $today); echo $trClass ? "" : ""; // QR / Kopfspalten if (Enable_QR_Code_CheckIn) { echo "
" . (new QRCode($options))->render($packingjob->packingnote_no) . "
"; } else { echo "" . $packingjob->packingnote_no . ""; } echo "" . $packingjob->contact->name . ""; echo "" . $packingjob->event . ""; // Zeitspalte öffnen, wenn mindestens eine Anzeige aktiv ist if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin || ShowDispoEndOnCheckin) { echo ""; } // Dispo-Ende (Check-In Termin) — ENDE korrekt verwendet if (ShowCheckInTimeOnCheckin && $packingjob->date_end != null) { echoMarkedTimeLine($packingjob->date_end, (int)$packingjob->time_end, $today, ShowTimesOnCheckin); } // Nachbereitung (START) — wie von dir bereits genutzt if (ShowNachbereitungTimeOnCheckin && $NachbereitungsTimeDetail && $NachbereitungsTimeDetail->date_start != null) { if (ShowCheckInTimeOnCheckin) echo "
"; echoMarkedTimeLine($NachbereitungsTimeDetail->date_start, (int)$NachbereitungsTimeDetail->time_start, $today, ShowTimesOnCheckin); } // Rückpacken (START) if (ShowRePackagingTimeOnCheckin && $RePackagingTimeDetail && $RePackagingTimeDetail->date_start != null) { if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin) echo "
"; echoMarkedTimeLine($RePackagingTimeDetail->date_start, (int)$RePackagingTimeDetail->time_start, $today, ShowTimesOnCheckin); } // Rücklieferung (REDELIVERY) — delivery ↔ redelivery gespiegelt if (ShowReDeliveryTimeOnCheckin && $PackingNoteDetail && $PackingNoteDetail->date_redelivery != null) { if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin) echo "
"; echoMarkedTimeLine($PackingNoteDetail->date_redelivery, (int)$PackingNoteDetail->time_redelivery, $today, ShowTimesOnCheckin); } // Dispo Ende if (ShowDispoEndOnCheckin && $DispoTimeDetail && $DispoTimeDetail->date_end != null) { if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin) echo "
"; echoMarkedTimeLine($DispoTimeDetail->date_end, (int)$DispoTimeDetail->time_end, $today, ShowTimesOnCheckin); } if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin || ShowDispoEndOnCheckin) { echo ""; } // Fortschritt echo ""; if ($packingjob->is_all_in == 0) { echo ""; } else { echo '
'; echo ""; } echo ( $packingjob->pieces_sum_total - abs($packingjob->is_all_out) - abs($packingjob->is_all_in)) . "/" . ($packingjob->pieces_sum_total - $packingjob->is_all_out) . " (" . $packingjob->pieces_sum_total . ")"; echo ""; // Shipping-Icons (inbound) if (ShowShippingIcons) { if (UseShippingStatus) { if (($PackingNoteDetail->status == ShippingInOrganizedStatus) || ($PackingNoteDetail->status == ShippingOrganizedStatus)) { echo ""; } else { echo ""; } if ($PackingNoteDetail->is_self_redeliver) { echo ''; } else { if (preg_match('/' . KurierContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } if (preg_match('/' . SpeditionContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } if (preg_match('/' . DHLContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } if (preg_match('/' . LKWContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } if (preg_match('/' . TransporterContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } if (preg_match('/' . PKWContainsText . '/i', $PackingNoteDetail->shipping_in)) { echo ''; } } echo ""; } echo ""; } echo ""; } } } function getTimeFromSeconds(string $timestring) { $hours = floor($timestring / 3600); $mins = floor($timestring / 60 % 60); $secs = floor($timestring % 60); $timeFormat = sprintf('%02d:%02d', $hours, $mins); return $timeFormat; }