getBasicSettings(); // 요일별 설정 조회 $weekly_settings = $this->getWeeklySettings(); // 해당 월의 모든 날짜 생성 $dates = $this->getMonthDates($year, $month); // 기존 스케줄 삭제 (자동 생성된 것만) $this->clearAutoGeneratedSchedule($year, $month); $generated_count = 0; foreach ($dates as $date) { $day_of_week = date('w', strtotime($date)); // 0=일요일, 1=월요일, ... $day_name = $this->getDayName($day_of_week); // 해당 요일의 설정 확인 if (isset($weekly_settings[$day_name]) && $weekly_settings[$day_name]['enabled'] == '1') { // 운영일인 경우 스케줄 생성 $slots_created = $this->generateDay($date, $weekly_settings[$day_name], $basic_settings); $generated_count += $slots_created; } else { // 휴무일인 경우 휴무 표시 $this->createHolidaySlot($date, '휴무일'); } } consultant_log("월별 스케줄 생성 완료: {$year}-{$month}, 생성된 슬롯: {$generated_count}개"); return $generated_count; } catch (Exception $e) { consultant_log("월별 스케줄 생성 실패: " . $e->getMessage(), 'error'); throw $e; } } /** * 특정 날짜의 스케줄 생성 */ public function generateDay($date, $day_settings, $basic_settings) { $slots_created = 0; try { $start_time = $day_settings['start']; $end_time = $day_settings['end']; $lunch_start = $day_settings['lunch_start']; $lunch_end = $day_settings['lunch_end']; $slot_duration = (int) $basic_settings['consultation_duration']; $max_persons = (int) $basic_settings['max_persons_per_slot']; // 시간 슬롯 생성 $current_time = strtotime($start_time); $end_timestamp = strtotime($end_time); while ($current_time < $end_timestamp) { $slot_start = date('H:i', $current_time); $slot_end = date('H:i', $current_time + ($slot_duration * 60)); // 종료시간이 운영시간을 넘지 않도록 체크 if (strtotime($slot_end) > $end_timestamp) { break; } // 점심시간 체크 $is_lunch_time = $this->isLunchTime($slot_start, $slot_end, $lunch_start, $lunch_end); if ($is_lunch_time) { // 점심시간 슬롯 생성 $this->createTimeSlot($date, $slot_start, $slot_end, $slot_duration, 0, 0, 'lunch_time'); } else { // 일반 상담 슬롯 생성 $this->createTimeSlot($date, $slot_start, $slot_end, $slot_duration, $max_persons, 1, 'auto_generated'); } $slots_created++; $current_time += ($slot_duration * 60); } return $slots_created; } catch (Exception $e) { consultant_log("일별 스케줄 생성 실패 ({$date}): " . $e->getMessage(), 'error'); throw $e; } } /** * 시간 슬롯 생성 */ private function createTimeSlot($date, $start_time, $end_time, $duration, $max_persons, $is_available, $type) { $sql = "INSERT INTO consultant_schedule (specific_date, start_time, end_time, time_slot, max_persons, is_available, temp_1, created_at) VALUES ('{$date}', '{$start_time}', '{$end_time}', {$duration}, {$max_persons}, {$is_available}, '{$type}', NOW())"; return sql_query($sql); } /** * 휴무일 슬롯 생성 */ private function createHolidaySlot($date, $reason = '휴무일') { $sql = "INSERT INTO consultant_schedule (specific_date, start_time, end_time, time_slot, max_persons, is_available, temp_1, temp_2, created_at) VALUES ('{$date}', '00:00', '23:59', 0, 0, 0, 'holiday', '{$reason}', NOW())"; return sql_query($sql); } /** * 점심시간 여부 확인 */ private function isLunchTime($slot_start, $slot_end, $lunch_start, $lunch_end) { if (empty($lunch_start) || empty($lunch_end)) { return false; } $slot_start_time = strtotime($slot_start); $slot_end_time = strtotime($slot_end); $lunch_start_time = strtotime($lunch_start); $lunch_end_time = strtotime($lunch_end); // 슬롯이 점심시간과 겹치는지 확인 return ($slot_start_time >= $lunch_start_time && $slot_start_time < $lunch_end_time) || ($slot_end_time > $lunch_start_time && $slot_end_time <= $lunch_end_time) || ($slot_start_time <= $lunch_start_time && $slot_end_time >= $lunch_end_time); } /** * 해당 월의 모든 날짜 배열 생성 */ private function getMonthDates($year, $month) { $dates = []; $days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, $year); for ($day = 1; $day <= $days_in_month; $day++) { $dates[] = sprintf('%04d-%02d-%02d', $year, $month, $day); } return $dates; } /** * 요일 숫자를 요일명으로 변환 */ private function getDayName($day_of_week) { $day_names = [ 0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday' ]; return $day_names[$day_of_week] ?? 'sunday'; } /** * 기본 설정 조회 */ private function getBasicSettings() { return [ 'consultation_duration' => consultant_get_config('consultation_duration', '60'), 'max_persons_per_slot' => consultant_get_config('max_persons_per_slot', '2'), 'consultation_fee' => consultant_get_config('consultation_fee', '50000') ]; } /** * 요일별 설정 조회 */ private function getWeeklySettings() { $days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']; $settings = []; foreach ($days as $day) { $settings[$day] = [ 'enabled' => consultant_get_config($day . '_enabled', $day == 'saturday' || $day == 'sunday' ? '0' : '1'), 'start' => consultant_get_config($day . '_start', '09:00'), 'end' => consultant_get_config($day . '_end', '18:00'), 'lunch_start' => consultant_get_config($day . '_lunch_start', '12:00'), 'lunch_end' => consultant_get_config($day . '_lunch_end', '13:00') ]; } return $settings; } /** * 자동 생성된 스케줄 삭제 */ private function clearAutoGeneratedSchedule($year, $month) { $start_date = sprintf('%04d-%02d-01', $year, $month); $end_date = sprintf('%04d-%02d-%02d', $year, $month, cal_days_in_month(CAL_GREGORIAN, $month, $year)); // 기존 예약이 없는 자동 생성 스케줄만 삭제 $sql = "DELETE cs FROM consultant_schedule cs LEFT JOIN consultant_reservations cr ON ( cs.specific_date = cr.reservation_date AND cs.start_time = cr.reservation_time AND cr.is_deleted = 0 ) WHERE cs.specific_date >= '{$start_date}' AND cs.specific_date <= '{$end_date}' AND cs.temp_1 IN ('auto_generated', 'lunch_time', 'holiday') AND cr.id IS NULL"; return sql_query($sql); } /** * 기존 예약 보호 - 예약이 있는 시간대 확인 */ public function getExistingReservations($year, $month) { $start_date = sprintf('%04d-%02d-01', $year, $month); $end_date = sprintf('%04d-%02d-%02d', $year, $month, cal_days_in_month(CAL_GREGORIAN, $month, $year)); $sql = "SELECT reservation_date, reservation_time, COUNT(*) as count FROM consultant_reservations WHERE reservation_date >= '{$start_date}' AND reservation_date <= '{$end_date}' AND is_deleted = 0 GROUP BY reservation_date, reservation_time"; $result = sql_query($sql); $reservations = []; if ($result) { while ($row = sql_fetch_array($result)) { $key = $row['reservation_date'] . '_' . $row['reservation_time']; $reservations[$key] = $row['count']; } } return $reservations; } /** * 다음 달 스케줄 자동 생성 (크론잡용) */ public function generateNextMonth() { $next_month = date('Y-m', strtotime('+1 month')); list($year, $month) = explode('-', $next_month); return $this->generateMonth((int) $year, (int) $month); } /** * 스케줄 생성 상태 확인 */ public function checkScheduleStatus($year, $month) { $start_date = sprintf('%04d-%02d-01', $year, $month); $end_date = sprintf('%04d-%02d-%02d', $year, $month, cal_days_in_month(CAL_GREGORIAN, $month, $year)); $sql = "SELECT COUNT(*) as total_slots, COUNT(CASE WHEN temp_1 = 'auto_generated' THEN 1 END) as auto_slots, COUNT(CASE WHEN temp_1 = 'lunch_time' THEN 1 END) as lunch_slots, COUNT(CASE WHEN temp_1 = 'holiday' THEN 1 END) as holiday_slots, COUNT(CASE WHEN temp_1 = 'admin_blocked' THEN 1 END) as blocked_slots FROM consultant_schedule WHERE specific_date >= '{$start_date}' AND specific_date <= '{$end_date}'"; return sql_fetch($sql); } /** * 설정 변경 시 영향받는 예약 확인 */ public function checkSettingConflicts($year, $month) { $existing_reservations = $this->getExistingReservations($year, $month); $conflicts = []; // 새로운 설정으로 생성될 스케줄과 기존 예약 비교 $weekly_settings = $this->getWeeklySettings(); $dates = $this->getMonthDates($year, $month); foreach ($dates as $date) { $day_of_week = date('w', strtotime($date)); $day_name = $this->getDayName($day_of_week); // 휴무일로 변경되었는데 예약이 있는 경우 if (!isset($weekly_settings[$day_name]) || $weekly_settings[$day_name]['enabled'] != '1') { foreach ($existing_reservations as $key => $count) { if (strpos($key, $date) === 0) { $conflicts[] = [ 'date' => $date, 'type' => 'holiday_conflict', 'message' => "{$date}는 휴무일로 설정되었지만 {$count}건의 예약이 있습니다." ]; } } } } return $conflicts; } } /** * 스케줄 생성 헬퍼 함수들 */ /** * 월별 스케줄 생성 실행 */ function generate_monthly_schedule($year, $month) { $generator = new ScheduleGenerator(); return $generator->generateMonth($year, $month); } /** * 다음 달 스케줄 자동 생성 */ function auto_generate_next_month_schedule() { $generator = new ScheduleGenerator(); return $generator->generateNextMonth(); } /** * 스케줄 생성 상태 확인 */ function get_schedule_generation_status($year, $month) { $generator = new ScheduleGenerator(); return $generator->checkScheduleStatus($year, $month); } /** * 설정 변경 영향 확인 */ function check_schedule_setting_conflicts($year, $month) { $generator = new ScheduleGenerator(); return $generator->checkSettingConflicts($year, $month); } ?>