setTime(0, 0, 0); } /** * Quelle für das Markierungsdatum (identisch zu deiner Liste): * 1 = $packingjob->date_start * 2 = $VorbereitungsTimeDetail->date_start * 3 = $PackingNoteDetail->date_packing * 4 = $PackingNoteDetail->date_delivery * Fallback: $packingjob->date_start */ function resolveRowMarkDate($packingjob, $VorbereitungsTimeDetail, $PackingNoteDetail, int $source): ?DateTimeImmutable { $candidate = null; switch ($source) { case 1: $candidate = dt($packingjob->date_start ?? null); break; case 2: $candidate = dt($VorbereitungsTimeDetail->date_start ?? null); break; case 3: $candidate = dt($PackingNoteDetail->date_packing ?? null); break; case 4: $candidate = dt($PackingNoteDetail->date_delivery ?? null); break; default:$candidate = null; break; } if (!$candidate) $candidate = dt($packingjob->date_start ?? null); return $candidate ? dayStart($candidate) : null; } /** ---- Daten laden wie bisher (Checkout-Quelle) ---- */ if (UseDeliveredForCheckOutCompleted) { // isco=False -> Checkout-Ansicht offen $result = $Epi->requestEpiApi('/v1/packingnote/open?isco=False&cl=' . Epirent_Mandant); } else { // isci=False -> Alternative Logik (wie in deiner Datei) $result = $Epi->requestEpiApi('/v1/packingnote/open?isci=False&cl=' . Epirent_Mandant); } $data_output = json_decode($result)->payload ?? []; /** ---- Zähler vorbereiten ---- */ $today = dayStart(new DateTimeImmutable('today', new DateTimeZone(APP_TZ))); $limit = null; // optionales Fenster wie in deiner Liste if (CheckOut_FutureDays != -1) { $limit = $today->modify('+' . (int)CheckOut_FutureDays . ' day'); } $cntOverdue = 0; $cntToday = 0; $cntFuture = 0; /** ---- Iteration identisch zur bisherigen Logik ---- */ foreach ($data_output as $packingjob) { // Details nur holen, wenn nötig & wie gehabt $PackingNoteDetail = null; if ($packingjob->is_archived != true && UseDeliveredForCheckOutCompleted) { $PackingNoteDetailResult = $Epi->requestEpiApi('/v1/packingnote/' . $packingjob->primary_key . '?cl=' . Epirent_Mandant); $PackingNoteDetail = json_decode($PackingNoteDetailResult)->payload[0] ?? null; } // Aufnahmebedingung exakt wie bei dir: if ( $packingjob->is_archived != true && ( !UseDeliveredForCheckOutCompleted || ($PackingNoteDetail && ($PackingNoteDetail->date_delivered !== "0000-00-00" || (int)$PackingNoteDetail->time_delivered !== 0)) ) && ($PackingNoteDetail && (int)$PackingNoteDetail->is_all_out !== 0) ) { // OrderDetails (für Vorbereitungszeit) $result = $Epi->requestEpiApi('/v1/order/' . $packingjob->order_pk . '?cl=' . Epirent_Mandant); $orderdetail_output = (json_decode($result)->payload[0] ?? null); // PackingNoteDetail nachladen, falls oben noch nicht geholt if (!UseDeliveredForCheckOutCompleted) { $PackingNoteDetailResult = $Epi->requestEpiApi('/v1/packingnote/' . $packingjob->primary_key . '?cl=' . Epirent_Mandant); $PackingNoteDetail = json_decode($PackingNoteDetailResult)->payload[0] ?? null; if (!$PackingNoteDetail) continue; } // Vorbereitungs-Zeitdetail ermitteln $VorbereitungsTimeDetail = null; if ($orderdetail_output && !empty($orderdetail_output->order_schedule)) { foreach ($orderdetail_output->order_schedule as $scheduledetail) { if ($scheduledetail->name == Vorbereitungs_Zeitvariable) { $VorbereitungsTimeDetail = $scheduledetail; break; } } } // Markierungsdatum wie in der Tabelle $markDate = resolveRowMarkDate($packingjob, $VorbereitungsTimeDetail, $PackingNoteDetail, (int)CheckOutRowMarkSource); if (!$markDate) continue; // Optionales Zukunftsfenster berücksichtigen (wie bisher) if (CheckOut_FutureDays != -1 && $limit && $markDate > $limit) { // außerhalb des Fensters ignorieren continue; } // Zählen if ($markDate < $today) { $cntOverdue++; } elseif ($markDate == $today) { $cntToday++; } else { // $markDate > $today $cntFuture++; } } } // Zeitstempel für die Karten $ts = (new DateTimeImmutable('now', new DateTimeZone(APP_TZ)))->format('H:i:s'); /** ---- Ausgabe: 3 Bootstrap-Karten ---- */ ?>

Checkout

Überfällige CheckOuts
Heutige CheckOuts
Zukünftige CheckOutsformat('d.m.Y').')' : '') ?>