d2d.emegrendeles.hu/tests/Feature/DeliveryCalendarServiceTest.php
E98Developer d26ba5e5e6 FIX EV3-466 hétvégi szállítási napok engedélyezése a heti sablonból
A DeliveryCalendarService 4. prioritása a WorkCalendarService::isWorkDay()-t
hívta, ami a naptárban nem szereplő napoknál a hétvégére esett vissza. Így egy
hétvégét is tartalmazó sablon szombat/vasárnap mezőit sosem érte el a
kiértékelés (5. prioritás), és csak egyedi felülbírálással lehetett hétvégi
szállítást engedni.

- WorkCalendarService: új isHoliday(), ami csak a work_calendars ünnepnap
  rekordjaira ad true-t, a naptári hétvégére nem. Az isWorkDay() változatlan.
- DeliveryCalendarService: a 4. prioritás mostantól isHoliday()-t használ, így
  a hétvégéről a heti sablon dönt. Ünnepnap továbbra is tilt.
- NextDeliveryDateCalculatorService: a szállítási nap keresése kikerült az
  isWorkDay() blokkból, különben a hétvége a következő szállítási nap
  számításánál továbbra is kimaradt volna. Az átfutási időbe az új
  countsTowardLeadTime() szerint a sablon hétvégi napjai is beleszámítanak,
  a H-P sablonok viselkedése változatlan.
- DeliveryCalendarWidget: a szürke "inaktív" festés csak a nem szállítási
  hétvégékre megy rá. Mellékesen a szállítási napok ciklusa $date->addDay()-jel
  mutálta a kollekció Carbon objektumait, ez copy()-ra javítva.

7 új teszt, köztük a H-P sablon regresszió-őre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:59:59 +02:00

342 lines
13 KiB
PHP

<?php
use App\Enums\OverrideScope;
use App\Models\DeliveryCalendarOverride;
use App\Models\DeliverySchedule;
use App\Models\ProfitCenter;
use App\Models\ProfitCenterSupplierSchedule;
use App\Models\Supplier;
use App\Models\WorkCalendar;
use App\Enums\WorkDayType;
use App\Enums\DataSource;
use App\Services\DeliveryCalendarService;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
uses(TestCase::class, RefreshDatabase::class);
it('returns true for a scheduled delivery day', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create([
'monday' => true,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$service = app(DeliveryCalendarService::class);
$monday = Carbon::parse('2026-04-13'); // Monday
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
});
it('returns false for a non-scheduled delivery day', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create([
'monday' => true,
'tuesday' => false,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$service = app(DeliveryCalendarService::class);
$tuesday = Carbon::parse('2026-04-14'); // Tuesday
expect($service->isDeliveryDay($pc, $supplier, $tuesday))->toBeFalse();
});
it('respects official holidays (WorkCalendar)', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13'); // Monday
// Mark this Monday as a holiday
WorkCalendar::create([
'date' => '2026-04-13',
'type' => WorkDayType::Holiday,
'data_source' => DataSource::Manual,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
});
it('respects general supplier override over holidays', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13'); // Monday
WorkCalendar::create([
'date' => '2026-04-13',
'type' => WorkDayType::Holiday,
'data_source' => DataSource::Manual,
]);
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::General->value,
'date' => '2026-04-13',
'is_delivery_day' => true,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
});
it('respects general supplier override to block delivery on a normal day', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13'); // Monday
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::General->value,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
});
it('respects delivery-schedule-specific override over general override', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13');
// Általános tiltás
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::General->value,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
// Szállítási sablon-specifikus engedélyezés
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::Region->value,
'delivery_schedule_id' => $schedule->id,
'date' => '2026-04-13',
'is_delivery_day' => true,
]);
$service = app(DeliveryCalendarService::class);
// A sablon-specifikus győz az általánossal szemben
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
});
it('delivery-schedule override does not affect profit centers with different schedule', function () {
$supplier = Supplier::factory()->create();
$scheduleA = DeliverySchedule::factory()->create(['monday' => true]);
$scheduleB = DeliverySchedule::factory()->create(['monday' => true]);
$pcA = ProfitCenter::factory()->create();
$pcB = ProfitCenter::factory()->create();
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pcA->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $scheduleA->id,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pcB->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $scheduleB->id,
]);
$monday = Carbon::parse('2026-04-13');
// Csak az A sablont tiltjuk
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::Region->value,
'delivery_schedule_id' => $scheduleA->id,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pcA, $supplier, $monday))->toBeFalse();
expect($service->isDeliveryDay($pcB, $supplier, $monday))->toBeTrue();
});
it('respects profit-center-specific override over region and general overrides', function () {
$pc = ProfitCenter::factory()->create(['city' => 'Budapest']);
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13');
// Általános tiltás
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::General->value,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
// Sablon-specifikus tiltás is
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::Region->value,
'delivery_schedule_id' => $schedule->id,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
// De erre a konkrét PC-re engedélyezve van
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::ProfitCenter->value,
'profit_center_id' => $pc->id,
'date' => '2026-04-13',
'is_delivery_day' => true,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
});
it('profit-center-specific override only affects the targeted profit center', function () {
$pc1 = ProfitCenter::factory()->create(['city' => 'Budapest']);
$pc2 = ProfitCenter::factory()->create(['city' => 'Budapest']);
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc1->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc2->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$monday = Carbon::parse('2026-04-13');
// Csak pc1-re van tiltás
DeliveryCalendarOverride::create([
'supplier_id' => $supplier->id,
'override_scope' => OverrideScope::ProfitCenter->value,
'profit_center_id' => $pc1->id,
'date' => '2026-04-13',
'is_delivery_day' => false,
]);
$service = app(DeliveryCalendarService::class);
expect($service->isDeliveryDay($pc1, $supplier, $monday))->toBeFalse();
expect($service->isDeliveryDay($pc2, $supplier, $monday))->toBeTrue();
});
it('calculates available delivery dates in a range', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create([
'monday' => true,
'wednesday' => true,
'friday' => true,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$start = Carbon::parse('2026-04-13'); // Monday
$end = Carbon::parse('2026-04-19'); // Sunday
$service = app(DeliveryCalendarService::class);
$dates = $service->getAvailableDeliveryDates($pc, $supplier, $start, $end);
// Should be Mon, Wed, Fri
expect($dates)->toHaveCount(3);
$dateStrings = $dates->map(fn($d) => $d->toDateString());
expect($dateStrings)->toContain('2026-04-13');
expect($dateStrings)->toContain('2026-04-15');
expect($dateStrings)->toContain('2026-04-17');
});
it('allows weekend delivery when the schedule includes it', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['saturday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$service = app(DeliveryCalendarService::class);
$saturday = Carbon::parse('2026-04-18'); // Saturday
expect($service->isDeliveryDay($pc, $supplier, $saturday))->toBeTrue();
});
it('still blocks weekends the schedule does not include', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['monday' => true, 'saturday' => false]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$service = app(DeliveryCalendarService::class);
$saturday = Carbon::parse('2026-04-18'); // Saturday
expect($service->isDeliveryDay($pc, $supplier, $saturday))->toBeFalse();
});
it('blocks official holidays even on a scheduled weekend day', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create(['saturday' => true]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
WorkCalendar::create([
'date' => '2026-04-18',
'type' => WorkDayType::Holiday,
'data_source' => DataSource::Manual,
]);
$service = app(DeliveryCalendarService::class);
$saturday = Carbon::parse('2026-04-18'); // Saturday
expect($service->isDeliveryDay($pc, $supplier, $saturday))->toBeFalse();
});
it('includes scheduled weekend days in an available date range', function () {
$pc = ProfitCenter::factory()->create();
$supplier = Supplier::factory()->create();
$schedule = DeliverySchedule::factory()->create([
'monday' => true,
'tuesday' => true,
'wednesday' => true,
'thursday' => true,
'friday' => true,
'saturday' => true,
'sunday' => true,
]);
ProfitCenterSupplierSchedule::factory()->create([
'profit_center_id' => $pc->id,
'supplier_id' => $supplier->id,
'delivery_schedule_id' => $schedule->id,
]);
$service = app(DeliveryCalendarService::class);
$dates = $service->getAvailableDeliveryDates(
$pc,
$supplier,
Carbon::parse('2026-04-13'), // Monday
Carbon::parse('2026-04-19'), // Sunday
);
expect($dates)->toHaveCount(7);
});