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, '该时间段技师已有其他订单' ); } }