d2d.emegrendeles.hu/app/Services/NextDeliveryDateCalculatorService.php
2026-04-25 05:54:05 +02:00

98 lines
3.2 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Services;
use App\Models\ProfitCenter;
use App\Models\ProfitCenterSupplierSchedule;
use App\Models\Supplier;
use Illuminate\Support\Carbon;
class NextDeliveryDateCalculatorService extends ServiceBase
{
public function __construct(
protected DeliveryCalendarService $deliveryCalendarService,
protected WorkCalendarService $workCalendarService,
) {
}
/**
* Meghatározza a következő szállítási napot egy adott supplierprofitcenter párosnál,
* a megrendelés leadásának dátuma és időpontja alapján.
*
* Ha a suppliernek van szállítási korlátozása (hasDeliveryConstraint), figyelembe veszi:
* - orderCutOffTime: leadási határidő (óra), ha előtte adjuk le, a nap beleszámít az átfutásba
* - deliveryLeadTime: szállítási átfutási idő (óra → munkanapban számítva)
*
* @param int $supplierId
* @param int $profitCenterId
* @param Carbon $orderDateTime A leadás dátuma és időpontja
* @return Carbon|null A következő lehetséges szállítási nap
*/
public function calculate(
int $supplierId,
int $profitCenterId,
Carbon $orderDateTime
): ?Carbon {
$assignment = ProfitCenterSupplierSchedule::where('supplier_id', $supplierId)
->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);
}
/**
* Munkanapokban számol előre ($leadDays darabot), majd az első olyan napot adja vissza,
* amelyik szállítási nap is.
*/
private function findNextDeliveryDay(
Carbon $candidate,
Supplier $supplier,
ProfitCenter $pc,
int $leadDays,
): ?Carbon {
$workingDaysCounted = 0;
// Max. 365 nap iteráció (végtelen ciklus-védelem)
for ($i = 0; $i < 365; $i++) {
if ($this->workCalendarService->isWorkDay($candidate)) {
if ($workingDaysCounted >= $leadDays) {
// Átfutási idő letelt az első szállítási napot keressük
if ($this->deliveryCalendarService->isDeliveryDay($pc, $supplier, $candidate)) {
return $candidate->copy();
}
} else {
$workingDaysCounted++;
}
}
$candidate->addDay();
}
return null;
}
}