123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- <?php
- namespace App\Services\Client\Traits;
- use App\Enums\OrderStatus;
- use App\Enums\TechnicianAuthStatus;
- use App\Enums\TechnicianStatus;
- use App\Models\CoachSchedule;
- use App\Models\CoachUser;
- use App\Models\Order;
- use Carbon\Carbon;
- trait ValidatesServiceTime
- {
- private function validateServiceTimeParams(int $coachId, string $serviceTime): void
- {
- // 验证技师状态
- $coach = CoachUser::where('id', $coachId)
- ->where('state', TechnicianStatus::ACTIVE->value)
- ->where('auth_state', TechnicianAuthStatus::PASSED->value)
- ->firstOrFail();
- // 验证时间格式
- $serviceDateTime = Carbon::parse($serviceTime);
- abort_if(
- $serviceDateTime->isPast(),
- 400,
- '服务时间不能早于当前时间'
- );
- // 验证预约提前时间(至少提前2小时)
- $minAdvanceHours = config('business.min_advance_hours', 2);
- abort_if(
- $serviceDateTime->diffInHours(now()) < $minAdvanceHours,
- 400,
- "需要至少提前{$minAdvanceHours}小时预约"
- );
- // 验证预约时间范围(最多提前7天)
- $maxAdvanceDays = config('business.max_advance_days', 7);
- abort_if(
- $serviceDateTime->diffInDays(now()) > $maxAdvanceDays,
- 400,
- "最多只能提前{$maxAdvanceDays}天预约"
- );
- }
- private function getCoachWorkSchedule(int $coachId): array
- {
- $schedule = CoachSchedule::where('coach_id', $coachId)
- ->where('state', 1)
- ->first();
- if (! $schedule) {
- return [
- 'work_days' => range(1, 7),
- 'work_hours' => [
- 'start' => '09:00',
- 'end' => '21:00',
- ],
- 'rest_dates' => [],
- ];
- }
- return [
- 'work_days' => json_decode($schedule->work_days, true),
- 'work_hours' => [
- 'start' => $schedule->work_start_time,
- 'end' => $schedule->work_end_time,
- ],
- 'rest_dates' => json_decode($schedule->rest_dates, true) ?? [],
- ];
- }
- private function validateWorkingHours(string $serviceTime, array $workSchedule): void
- {
- $serviceDateTime = Carbon::parse($serviceTime);
- // 检查工作日
- $dayOfWeek = $serviceDateTime->dayOfWeek;
- abort_if(
- ! in_array($dayOfWeek, $workSchedule['work_days']),
- 400,
- '该时间不在技师工作日内'
- );
- // 检查特殊休息日
- $dateStr = $serviceDateTime->format('Y-m-d');
- abort_if(
- in_array($dateStr, $workSchedule['rest_dates']),
- 400,
- '技师该日期休息'
- );
- // 检查工作时间
- $timeStr = $serviceDateTime->format('H:i');
- $startTime = Carbon::parse($workSchedule['work_hours']['start']);
- $endTime = Carbon::parse($workSchedule['work_hours']['end']);
- abort_if(
- $timeStr < $startTime->format('H:i') || $timeStr > $endTime->format('H:i'),
- 400,
- sprintf(
- '服务时间需在%s-%s之间',
- $startTime->format('H:i'),
- $endTime->format('H:i')
- )
- );
- }
- private function checkTimeConflicts(int $coachId, string $serviceTime): void
- {
- $serviceDateTime = Carbon::parse($serviceTime);
- // 获取服务时长(默认2小时)
- $serviceDuration = config('business.default_service_duration', 120);
- // 计算服务结束时间
- $serviceEndTime = $serviceDateTime->copy()->addMinutes($serviceDuration);
- // 检查是否有其他订单在这个时间段
- $conflictOrder = Order::where('coach_id', $coachId)
- ->whereIn('state', [
- OrderStatus::PAID->value,
- OrderStatus::ACCEPTED->value,
- OrderStatus::SERVING->value,
- ])
- ->where(function ($query) use ($serviceDateTime, $serviceEndTime) {
- $query->where(function ($q) use ($serviceDateTime) {
- // 新订单开始时间在其他订单的服务时间段内
- $q->where('service_time', '<=', $serviceDateTime)
- ->where('service_end_time', '>', $serviceDateTime);
- })->orWhere(function ($q) use ($serviceEndTime) {
- // 新订单结束时间在其他订单的服务时间段内
- $q->where('service_time', '<', $serviceEndTime)
- ->where('service_end_time', '>=', $serviceEndTime);
- });
- })
- ->first();
- abort_if(
- $conflictOrder,
- 400,
- '该时间段技师已有其他订单'
- );
- }
- }
|