createUser(['ROLE_DOCTOR']); $doctor = new Doctor($owner, 'دکتر سرویس'); $this->em->persist($doctor); // فردا در بازهٔ booking-window قرار دارد و روز گذشته نیست. $date = date('Y-m-d', strtotime('tomorrow')); $dayKey = (string)(((int) date('w', strtotime($date)) + 1) % 7); $schedule = $this->newWeeklySchedule($doctor, [ $dayKey => ['sessions' => [[ 'active' => true, 'start_time' => '15:00', 'end_time' => '17:00', 'duration_per_patient' => 20, 'location_id' => 1, ]]], ]); $schedule->setMeta(['booking_mode' => WeeklySchedule::MODE_SERVICE, 'buffer_minutes' => $buffer]); $this->em->persist($schedule); $this->em->flush(); return [$doctor, $date]; } public function testGapPackingWithBuffer(): void { [$doctor, $date] = $this->makeDoctorWithServiceSchedule(5); $calc = static::getContainer()->get(SlotCalculatorService::class); $slots = $calc->getServiceStartTimes($doctor, $date, 30); // پنجره 15:00–17:00، سرویس 30 + بافر 5 → گام 35 دقیقه: 15:00, 15:35, 16:10 $times = array_column($slots, 'start_time'); $this->assertSame(['15:00', '15:35', '16:10'], $times); // زمان پایانِ ذخیره‌شده بدون بافر است. $this->assertSame(strtotime($date . ' 15:00') + 30 * 60, $slots[0]['end']); } public function testBookedIntervalIsSkipped(): void { [$doctor, $date] = $this->makeDoctorWithServiceSchedule(5); $patient = $this->createUser(['ROLE_USER']); $start = strtotime($date . ' 15:00'); $appt = $this->newAppointment($doctor, $patient, $start, $start + 30 * 60); $appt->transitionTo(Appointment::STATUS_CONFIRMED); $this->em->persist($appt); $this->em->flush(); $calc = static::getContainer()->get(SlotCalculatorService::class); $times = array_column($calc->getServiceStartTimes($doctor, $date, 30), 'start_time'); // 15:00 اشغال است → از 15:30 شروع می‌شود. $this->assertNotContains('15:00', $times); $this->assertContains('15:30', $times); } public function testNoRoomReturnsEmpty(): void { [$doctor, $date] = $this->makeDoctorWithServiceSchedule(0); // سرویس 200 دقیقه در پنجرهٔ 120 دقیقه‌ای جا نمی‌شود. $calc = static::getContainer()->get(SlotCalculatorService::class); $this->assertSame([], $calc->getServiceStartTimes($doctor, $date, 200)); } public function testMetaDefaultsAndWhitelist(): void { $owner = $this->createUser(['ROLE_DOCTOR']); $doctor = new Doctor($owner, 'دکتر متا'); $schedule = $this->newWeeklySchedule($doctor, []); // پیش‌فرض = اسلاتی $this->assertSame(WeeklySchedule::MODE_SLOT, $schedule->getMeta()['booking_mode']); $this->assertSame(0, $schedule->getMeta()['buffer_minutes']); $schedule->setMeta(['booking_mode' => 'service', 'buffer_minutes' => 7]); $this->assertSame('service', $schedule->getMeta()['booking_mode']); $this->assertSame(7, $schedule->getMeta()['buffer_minutes']); // مقدار نامعتبر mode نادیده گرفته می‌شود (whitelist)، بافر منفی → صفر. $schedule->setMeta(['booking_mode' => 'bogus', 'buffer_minutes' => -3]); $this->assertSame('service', $schedule->getMeta()['booking_mode']); $this->assertSame(0, $schedule->getMeta()['buffer_minutes']); } }