feat(doctor): update schedule fields in doctor API responses to reflect actual availability

This commit is contained in:
hamed
2026-06-15 15:11:29 +03:30
parent ec36eefeb8
commit c662eb9b4f
5 changed files with 398 additions and 28 deletions
+83 -8
View File
@@ -2,6 +2,7 @@
namespace App\Doctor\Entity;
use App\Appointment\Entity\WeeklySchedule;
use App\Auth\Entity\User;
use App\DoctorService\Entity\DoctorService;
use App\Location\Entity\City;
@@ -167,6 +168,78 @@ class Doctor
private function touch(): void { $this->updatedAt = time(); }
private const DAY_NAMES = ['شنبه', 'یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه'];
private function computeScheduleFields(?WeeklySchedule $schedule): array
{
if ($schedule === null) {
return ['free_turn' => 'نوبت آزادی موجود نیست', 'hours_of_work' => 'برنامه کاری تنظیم نشده', 'has_schedule' => false];
}
$setting = $schedule->getSetting();
// استخراج ساعت‌های هر روز — key: dayIdx، value: رشته ساعت‌ها یا null
$dayTimes = [];
for ($i = 0; $i < 7; $i++) {
$activeSessions = array_values(array_filter(
$setting[$i]['sessions'] ?? [],
fn($s) => ($s['active'] ?? false) && !empty($s['start_time'])
));
$dayTimes[$i] = empty($activeSessions)
? null
: implode(' و ', array_map(fn($s) => $s['start_time'] . '' . $s['end_time'], $activeSessions));
}
$hasAnyDay = array_filter($dayTimes) !== [];
if (!$hasAnyDay) {
return ['free_turn' => 'نوبت آزادی موجود نیست', 'hours_of_work' => 'برنامه کاری تنظیم نشده', 'has_schedule' => false];
}
// گروه‌بندی روزهای متوالی با ساعت یکسان
// مثال: شنبه–پنجشنبه ۹–۱۳ و ۱۴–۱۸ | جمعه تعطیل
$groups = [];
$current = ['start' => 0, 'times' => $dayTimes[0]];
for ($i = 1; $i < 7; $i++) {
if ($dayTimes[$i] === $current['times']) {
continue; // ادامه همان گروه
}
if ($current['times'] !== null) {
$groups[] = ['start' => $current['start'], 'end' => $i - 1, 'times' => $current['times']];
}
$current = ['start' => $i, 'times' => $dayTimes[$i]];
}
if ($current['times'] !== null) {
$groups[] = ['start' => $current['start'], 'end' => 6, 'times' => $current['times']];
}
$parts = [];
foreach ($groups as $g) {
$parts[] = $g['start'] === $g['end']
? self::DAY_NAMES[$g['start']]
: self::DAY_NAMES[$g['start']] . ' تا ' . self::DAY_NAMES[$g['end']];
}
// نزدیک‌ترین روز کاری — PHP date('w'): 0=Sun,6=Sat → ایندکس ایرانی: 0=Sat,...,6=Fri
$phpDay = (int) date('w');
$iranDay = $phpDay === 0 ? 1 : ($phpDay === 6 ? 0 : $phpDay + 1);
$freeTurn = null;
for ($i = 0; $i < 7; $i++) {
$idx = ($iranDay + $i) % 7;
if ($dayTimes[$idx] !== null) {
$firstTime = explode(' و ', $dayTimes[$idx])[0];
$freeTurn = self::DAY_NAMES[$idx] . ' ' . $firstTime;
break;
}
}
return [
'free_turn' => $freeTurn ?? 'نوبت آزادی موجود نیست',
'hours_of_work' => implode(' | ', $parts),
'has_schedule' => true,
];
}
public function getExperience(): int
{
if ($this->activityTime === null) {
@@ -175,8 +248,9 @@ class Doctor
return max(0, (int)((time() - $this->activityTime) / (365.25 * 24 * 3600)));
}
public function toListArray(): array
public function toListArray(?WeeklySchedule $schedule = null): array
{
$sf = $this->computeScheduleFields($schedule);
return [
'id' => (string) $this->id,
'uuid' => $this->uuid,
@@ -189,14 +263,15 @@ class Doctor
], $this->specialties->toArray()),
'satisfaction' => (string) $this->doctorRatePercentage,
'point' => (string) $this->doctorRate,
'free_turn' => 'نوبت آزادی موجود نیست',
'hours_of_work' => 'برنامه کاری تنظیم نشده',
'active' => $this->activeDoctorAppointment,
'free_turn' => $sf['free_turn'],
'hours_of_work' => $sf['hours_of_work'],
'active' => $this->activeDoctorAppointment && $sf['has_schedule'],
];
}
public function toDetailArray(): array
public function toDetailArray(?WeeklySchedule $schedule = null): array
{
$sf = $this->computeScheduleFields($schedule);
return [
'id' => (string) $this->id,
'uuid' => $this->uuid,
@@ -211,15 +286,15 @@ class Doctor
'uuid' => $s->getUuid(), 'id' => (string) $s->getId(), 'name' => $s->getName(),
'parent_id' => $s->getParent()?->getId() !== null ? (string) $s->getParent()->getId() : null,
], $this->specialties->toArray()),
'active' => $this->activeDoctorAppointment,
'active' => $this->activeDoctorAppointment && $sf['has_schedule'],
'img' => $this->images ?? [],
'expertise' => array_map(fn(DoctorService $ds) => [
'uuid' => $ds->getUuid(), 'id' => (string) $ds->getId(), 'name' => $ds->getName(),
], $this->services->toArray()),
'satisfaction' => (string) $this->doctorRatePercentage,
'point' => (string) $this->doctorRate,
'free_turn' => 'نوبت آزادی موجود نیست',
'hours_of_work' => 'برنامه کاری تنظیم نشده',
'free_turn' => $sf['free_turn'],
'hours_of_work' => $sf['hours_of_work'],
'address' => array_map(fn(DoctorAddress $a) => $a->toArray(), $this->addresses->toArray()),
'average_rate' => ['total_rates' => null],
'state' => array_map(fn(Province $p) => [