# 대관/대여 게시판 설계 문서

## 1. 개요

### 1.1 목적
- 시설(룸) 대관 예약 시스템
- 물품 대여 예약 시스템 (대관 기반 확장)

### 1.2 새 모드명
- `rental` : 대관/대여 게시판 모드

---

## 2. 데이터 구조

### 2.1 관리자 설정 (rental_config)

```json
{
  "rental_config": {
    // === 기본 설정 ===
    "time_settings": {
      "start_hour": 9,           // 운영 시작 시간 (0-23)
      "end_hour": 22,            // 운영 종료 시간 (1-24)
      "slot_duration": 60,       // 예약 단위 시간 (분) - 30, 60, 90, 120
      "break_duration": 0        // 사이 간격/휴식 시간 (분) - 0, 10, 15, 30
    },

    // === 휴일 설정 ===
    "holiday_settings": {
      "weekly_off": [0],         // 주간 휴일 (0=일, 1=월, ..., 6=토) 복수선택
      "specific_dates": [        // 개별 휴일 (YYYY-MM-DD 형식)
        "2025-01-01",
        "2025-12-25"
      ],
      "use_public_holidays": true  // 공휴일 자동 적용 여부
    },

    // === 룸(시설) 설정 ===
    "rooms": [
      {
        "id": "room_1",
        "name": "대회의실",
        "capacity": 50,                    // 수용 인원 (표시용)
        "limit_per_slot": true,            // 시간당 신청자 제한 여부
        "max_per_slot": 1,                 // 시간당 최대 예약 가능 수 (제한 시)
        "allow_waitlist": true,            // 대기자 허용 여부 (제한 미사용 시 자동 true)
        "enabled": true,                   // 활성화 여부
        "description": "",                 // 룸 설명
        "sort_order": 1                    // 정렬 순서
      },
      {
        "id": "room_2",
        "name": "소회의실 A",
        "capacity": 10,
        "limit_per_slot": false,
        "max_per_slot": 1,
        "allow_waitlist": true,
        "enabled": true,
        "description": "",
        "sort_order": 2
      }
    ],

    // === 예약 규칙 ===
    "booking_rules": {
      "min_advance_days": 1,      // 최소 며칠 전 예약 가능
      "max_advance_days": 30,     // 최대 며칠 전까지 예약 가능
      "max_slots_per_booking": 3, // 한 번에 최대 연속 시간 예약 가능
      "require_approval": false   // 관리자 승인 필요 여부
    },

    // === 라벨 매핑 (기존 label_config 연동) ===
    "status_labels": {
      "confirmed": "예약확정",    // 정원 내 자동 확정
      "waiting": "대기",          // 대기자
      "cancelled": "취소",        // 취소됨
      "completed": "완료"         // 이용 완료
    }
  }
}
```

### 2.2 예약 데이터 저장 (게시글 여분필드 활용)

**※ wr_3은 탭 설정, wr_10은 관리자 메모로 사용하므로 피함**

```
wr_1  : 라벨 (예약확정, 대기, 취소, 완료) - 기존 label_config 연동
wr_2  : 접수번호 (기존 receipt_config 활용)
wr_3  : [사용안함 - 탭 설정용으로 예약]
wr_4  : 예약 날짜 (YYYY-MM-DD)
wr_5  : 룸 ID (room_1, room_2, ...)
wr_6  : 예약 시간 슬롯 (JSON: ["10:00-11:00", "11:00-12:00"])
wr_7  : 예약자 연락처 (전화번호)
wr_8  : 예약자 이메일
wr_9  : 인원수
wr_10 : [사용안함 - 관리자 메모용으로 예약]
wr_11 : 예약 목적/용도
wr_12~: 기타 폼 설정 필드들 (기존 폼 설정 기반)
```

### 2.3 예약 현황 캐시 파일

빠른 조회를 위해 날짜별 예약 현황을 별도 캐시:

```
/data/hayan_total_data/rental_cache_{bo_table}_{YYYY-MM}.json
```

```json
{
  "2025-01-15": {
    "room_1": {
      "10:00-11:00": {
        "confirmed": ["wr_id_123"],
        "waiting": ["wr_id_456", "wr_id_789"]
      },
      "11:00-12:00": {
        "confirmed": [],
        "waiting": []
      }
    },
    "room_2": {
      // ...
    }
  }
}
```

---

## 3. 관리자 설정 UI

### 3.1 왼쪽 메뉴 추가

board_mode가 `rental`일 때 왼쪽 패널에 추가 메뉴 표시:
- 기본 설정 (시간, 휴일)
- 룸 관리
- 예약 현황 보기

### 3.2 기본 설정 섹션

```
┌─────────────────────────────────────────────────────────┐
│ 📅 대관 기본 설정                                         │
├─────────────────────────────────────────────────────────┤
│                                                         │
│ ▸ 운영 시간                                              │
│   시작: [09] 시  ~  종료: [22] 시                         │
│                                                         │
│ ▸ 예약 단위                                              │
│   [● 30분] [○ 60분] [○ 90분] [○ 120분]                   │
│                                                         │
│ ▸ 사이 간격(휴식) 시간                                    │
│   [● 없음] [○ 10분] [○ 15분] [○ 30분]                    │
│                                                         │
├─────────────────────────────────────────────────────────┤
│ ▸ 휴일 설정                                              │
│                                                         │
│   주간 휴일: [☑ 일] [☐ 월] [☐ 화] [☐ 수] [☐ 목] [☐ 금] [☑ 토] │
│                                                         │
│   [☑] 공휴일 자동 적용                                    │
│                                                         │
│   개별 휴일:                                             │
│   ┌─────────────────┐                                   │
│   │ 2025-01-01      │ [×]                               │
│   │ 2025-12-25      │ [×]                               │
│   │ [+ 휴일 추가]    │                                   │
│   └─────────────────┘                                   │
│                                                         │
├─────────────────────────────────────────────────────────┤
│ ▸ 예약 규칙                                              │
│                                                         │
│   최소 예약 가능: [1] 일 전부터                           │
│   최대 예약 가능: [30] 일 전까지                          │
│   연속 예약 최대: [3] 타임                                │
│   [☐] 관리자 승인 필요                                   │
│                                                         │
└─────────────────────────────────────────────────────────┘
```

### 3.3 룸 관리 섹션

```
┌─────────────────────────────────────────────────────────┐
│ 🏢 룸(시설) 관리                                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ≡  대회의실                                    [삭제] │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ 룸 이름: [대회의실          ]                        │ │
│ │ 수용 인원: [50] 명                                   │ │
│ │                                                     │ │
│ │ [☑] 시간당 신청자 수 제한                            │ │
│ │     └ 최대 예약 수: [1] 건                          │ │
│ │                                                     │ │
│ │ ※ 제한 초과 시 대기자로 등록됩니다                    │ │
│ │ [☑] 활성화                                          │ │
│ └─────────────────────────────────────────────────────┘ │
│                                                         │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ≡  소회의실 A                                  [삭제] │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ 룸 이름: [소회의실 A        ]                        │ │
│ │ 수용 인원: [10] 명                                   │ │
│ │                                                     │ │
│ │ [☐] 시간당 신청자 수 제한                            │ │
│ │     └ 대기자 무제한 가능                             │ │
│ │                                                     │ │
│ │ [☑] 활성화                                          │ │
│ └─────────────────────────────────────────────────────┘ │
│                                                         │
│                  [+ 룸 추가]                            │
│                                                         │
└─────────────────────────────────────────────────────────┘
```

---

## 4. 글쓰기 페이지 (예약 폼)

### 4.1 레이아웃 구조

```
┌─────────────────────────────────────────────────────────────────┐
│                     📅 시설 예약                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ ┌─── 날짜 선택 ───────────┐ ┌─── 룸 & 시간 선택 ─────────────┐  │
│ │                        │ │                                │  │
│ │      2025년 1월        │ │  ▼ 대회의실 (50명)              │  │
│ │  일 월 화 수 목 금 토  │ │  ├─────────────────────────────┤  │
│ │     1  2  3  4        │ │  │ 09:00~10:00  [예약가능] 🔵  │  │
│ │  5  6  7  8  9 10 11  │ │  │ 10:00~11:00  [예약완료] ⚫  │  │
│ │ 12 13 14 ⓯ 16 17 18  │ │  │ 11:00~12:00  [대기가능] 🟢  │  │
│ │ 19 20 21 22 23 24 25  │ │  │ 12:00~13:00  [예약가능] 🔵  │  │
│ │ 26 27 28 29 30 31     │ │  │ ...                         │  │
│ │                        │ │  └─────────────────────────────┤  │
│ │  ⚫ 휴일  ⚪ 예약불가   │ │                                │  │
│ │                        │ │  ▶ 소회의실 A (10명) [접힘]     │  │
│ └────────────────────────┘ │  ▶ 소회의실 B (10명) [접힘]     │  │
│                            │                                │  │
│                            └────────────────────────────────┘  │
│                                                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ ┌─── 선택한 예약 정보 ──────────────────────────────────────────┐ │
│ │                                                             │ │
│ │  📅 2025-01-15 (수)                                         │ │
│ │  🏢 대회의실                                                 │ │
│ │  ⏰ 09:00 ~ 10:00 (1시간)                                   │ │
│ │                                                             │ │
│ └─────────────────────────────────────────────────────────────┘ │
│                                                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ ┌─── 예약자 정보 (기존 폼 설정 기반) ───────────────────────────┐ │
│ │                                                             │ │
│ │  이름 *        [                    ]                       │ │
│ │  연락처 *      [                    ]                       │ │
│ │  이메일        [                    ]                       │ │
│ │  인원수 *      [    ] 명                                    │ │
│ │  이용 목적 *   [                    ]                       │ │
│ │  기타 요청사항 [                                           ]│ │
│ │                                                             │ │
│ │  [☑] 개인정보 수집 및 이용에 동의합니다                      │ │
│ │                                                             │ │
│ └─────────────────────────────────────────────────────────────┘ │
│                                                                 │
│                         [예약 신청]                             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### 4.2 시간 슬롯 상태 표시

| 상태 | 색상 | 설명 |
|------|------|------|
| 예약가능 | 🔵 파란색 | 정원 내 예약 가능 (클릭 시 선택) |
| 예약완료 | ⚫ 회색 | 정원 마감 (선택 불가) |
| 대기가능 | 🟢 녹색 | 정원 초과 but 대기 신청 가능 |
| 휴일 | 빨간색 배경 | 휴일로 예약 불가 |

### 4.3 시간 슬롯 선택 로직

```javascript
// 시간 슬롯 클릭 시
function selectTimeSlot(roomId, slotTime, status) {
    if (status === 'unavailable') {
        return; // 선택 불가
    }

    if (status === 'available') {
        // 정원 내 → 예약확정 라벨로 저장
        selectedLabel = '예약확정';
    } else if (status === 'waitlist') {
        // 대기 가능 → 대기 라벨로 저장
        selectedLabel = '대기';
        showWaitlistNotice(); // "대기자로 등록됩니다" 안내
    }

    updateSelectedInfo(roomId, slotTime);
}
```

---

## 5. 예약 처리 로직

### 5.1 예약 저장 흐름

```
1. 폼 제출
   ↓
2. 예약 가능 여부 재확인 (동시 예약 방지)
   ↓
3. 현재 해당 슬롯 예약 수 조회
   ↓
4. 정원 비교
   ├─ 정원 내 → 라벨: "예약확정"
   └─ 정원 초과 → 라벨: "대기"
   ↓
5. 게시글 저장 (wr_1~wr_12에 예약 정보, wr_3/wr_10 제외)
   ↓
6. 캐시 업데이트
   ↓
7. 완료 페이지 이동
```

### 5.2 예약 현황 조회 (AJAX)

```php
// ajax_rental_slots.php
// 특정 날짜의 모든 룸/시간 예약 현황 반환

$date = $_GET['date']; // YYYY-MM-DD
$bo_table = $_GET['bo_table'];

// 해당 날짜 예약 데이터 조회
// wr_4: 예약날짜, wr_5: 룸ID, wr_6: 시간슬롯
$sql = "SELECT wr_id, wr_1, wr_5, wr_6
        FROM {$write_table}
        WHERE wr_4 = '{$date}'
        AND wr_1 NOT IN ('취소')";

// 룸별/시간별 예약 수 집계
$slots = [];
foreach ($rows as $row) {
    $room_id = $row['wr_5'];
    $times = json_decode($row['wr_6'], true);
    $label = $row['wr_1'];

    foreach ($times as $time) {
        $slots[$room_id][$time][$label][] = $row['wr_id'];
    }
}

// 룸 설정과 비교하여 상태 결정
foreach ($rooms as $room) {
    foreach ($time_slots as $slot) {
        $confirmed = count($slots[$room['id']][$slot]['예약확정'] ?? []);

        if ($room['limit_per_slot'] && $confirmed >= $room['max_per_slot']) {
            if ($room['allow_waitlist']) {
                $status = 'waitlist';
            } else {
                $status = 'unavailable';
            }
        } else {
            $status = 'available';
        }
    }
}
```

---

## 6. 리스트 페이지

### 6.1 관리자 뷰 (달력형 + 리스트형 전환)

```
┌─────────────────────────────────────────────────────────────────┐
│ 📅 예약 현황                     [달력보기] [리스트보기]          │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│        2025년 1월           [◀ 이전] [다음 ▶]                   │
│ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐                    │
│ │ 일  │ 월  │ 화  │ 수  │ 목  │ 금  │ 토  │                    │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┤                    │
│ │     │     │     │  1  │  2  │  3  │  4  │                    │
│ │     │     │     │     │     │ 2건 │     │                    │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┤                    │
│ │  5  │  6  │  7  │  8  │  9  │ 10  │ 11  │                    │
│ │ 휴일│     │     │ 1건 │ 3건 │     │ 휴일│                    │
│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┘                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### 6.2 리스트형 (기존 스킨 활용)

기존 list.skin.php 구조 활용, 컬럼 설정에 따라 표시:
- 예약일, 룸명, 시간, 예약자, 상태(라벨)

---

## 7. 파일 구조

### 7.1 새로 생성할 파일

```
/theme/hayan/mobile/skin/board/hayan_total/
├── list_Rental.php              # 대관 리스트 (달력 뷰)
├── write_Rental.php             # 대관 예약 폼
├── ajax_rental_slots.php        # 예약 현황 AJAX
├── ajax_rental_save.php         # 예약 저장 AJAX
└── rental_helper.php            # 대관 헬퍼 함수

/adm2/
├── hytotal_form_config.php      # 수정: rental 모드 추가
└── hytotal_form_config_save.php # 수정: rental_config 저장
```

### 7.2 수정할 파일

```
hytotal_form_config.php
- board_mode 라디오에 'rental' 추가
- rental_settings 섹션 HTML 추가
- toggleBoardMode() JS 수정

hytotal_form_config_save.php
- rental_config 저장 로직 추가
- allowed_modes 배열에 'rental' 추가

list.skin.php
- rental 모드 분기 추가 (list_Rental.php include)

write.skin.php
- rental 모드 분기 추가 (write_Rental.php include)
```

---

## 8. 구현 우선순위

### Phase 1: 기본 인프라
1. rental_config 데이터 구조 정의
2. 관리자 설정 UI (기본설정, 룸관리)
3. 설정 저장/로드 로직

### Phase 2: 예약 기능
4. 예약 폼 (달력 + 룸 + 시간 선택)
5. 예약 현황 AJAX API
6. 예약 저장 로직

### Phase 3: 관리 기능
7. 리스트 페이지 (달력 뷰)
8. 예약 상태 관리 (확정↔대기↔취소)
9. 캐시 최적화

### Phase 4: 확장
10. 대여 모드 확장 (물품 대여)
11. 알림 기능 (SMS, 이메일)
12. 통계/리포트

---

## 9. 기술적 고려사항

### 9.1 동시성 처리
- 예약 저장 시 트랜잭션 또는 파일 락 사용
- 저장 직전 재확인 쿼리

### 9.2 성능 최적화
- 월별 캐시 파일로 빠른 조회
- 캐시 무효화: 예약 생성/수정/삭제 시

### 9.3 공휴일 데이터
- 한국 공휴일 API 또는 정적 데이터 사용
- 매년 초 업데이트 필요

---

## 10. 라벨 설정 연동

기존 label_config를 활용하여 예약 상태 관리:

```json
{
  "label_config": {
    "enabled": true,
    "labels": [
      { "name": "예약확정", "color": "#10b981" },
      { "name": "대기", "color": "#f59e0b" },
      { "name": "취소", "color": "#ef4444" },
      { "name": "완료", "color": "#6b7280" }
    ]
  }
}
```

rental 모드 선택 시 기본 라벨 자동 생성 옵션 제공.
