where('profit_center_id', $profitCenterId) ->with('deliverySchedule') ->first(); if (! $assignment?->deliverySchedule) { return null; } $supplier = Supplier::find($supplierId); $pc = ProfitCenter::find($profitCenterId); if (! $supplier || ! $pc) { return null; } $leadDays = 0; $startDay = $orderDateTime->copy()->startOfDay(); if ($supplier->hasDeliveryConstraint) { $cutOffHour = (int) $supplier->orderCutOffTime; $leadDays = (int) ($supplier->deliveryLeadTime / 24); // Ha a leadási határidő UTÁN vagyunk, holnap az első számítandó munkanap if ($orderDateTime->hour >= $cutOffHour) { $startDay->addDay(); } } return $this->findNextDeliveryDay($startDay, $supplier, $pc, $leadDays, $assignment); } /** * Előreszámol $leadDays darab átfutási napot, majd az első olyan napot adja vissza, * amelyik szállítási nap is. * * A szállítási nap keresése NINCS munkanaphoz kötve: hétvégi szállítást a heti sablon * engedhet, ezt az isDeliveryDay() dönti el (EV3-466). */ private function findNextDeliveryDay( Carbon $candidate, Supplier $supplier, ProfitCenter $pc, int $leadDays, ProfitCenterSupplierSchedule $assignment, ): ?Carbon { $leadDaysCounted = 0; // Max. 365 nap iteráció (végtelen ciklus-védelem) for ($i = 0; $i < 365; $i++) { if ($leadDaysCounted >= $leadDays) { // Átfutási idő letelt – az első szállítási napot keressük if ($this->deliveryCalendarService->isDeliveryDay($pc, $supplier, $candidate, $assignment)) { return $candidate->copy(); } } elseif ($this->countsTowardLeadTime($candidate, $assignment)) { $leadDaysCounted++; } $candidate->addDay(); } return null; } /** * Eldönti, hogy az adott nap beleszámít-e az átfutási idő visszaszámolásába. * * A hivatalos munkanapokon túl beleszámítanak azok a hétvégi napok is, amelyeket a * PC-hez rendelt heti sablon szállítási napként jelöl – egy 7 napos sablonnál tehát * minden nap telik, egy H–P sablonnál viszont a hétvége változatlanul nem (EV3-466). * Munkaszüneti napon sosem telik az átfutás. */ private function countsTowardLeadTime(Carbon $date, ProfitCenterSupplierSchedule $assignment): bool { if ($this->workCalendarService->isHoliday($date)) { return false; } if ($this->workCalendarService->isWorkDay($date)) { return true; } $schedule = $assignment->deliverySchedule; if (! $schedule || ! $schedule->is_active) { return false; } return (bool) $schedule->{strtolower($date->format('l'))}; } }