# Scheduled Tasks - การตั้งค่าและใช้งาน

## 📋 สารบัญ

1. [ภาพรวม](#ภาพรวม)
2. [Scheduled Tasks ที่มี](#scheduled-tasks-ที่มี)
3. [การตั้งค่า](#การตั้งค่า)
4. [การทดสอบ](#การทดสอบ)
5. [การใช้งานใน Production](#การใช้งานใน-production)
6. [การตรวจสอบ Logs](#การตรวจสอบ-logs)
7. [การแก้ไขปัญหา](#การแก้ไขปัญหา)

---

## ภาพรวม

ระบบใช้ Laravel Scheduler เพื่อรัน Scheduled Tasks อัตโนมัติตามเวลาที่กำหนด มี 2 tasks หลัก:

1. **ตรวจสอบวันหมดอายุของแบบประเมิน** - อัปเดตสถานะแบบประเมินที่หมดอายุเป็น `expired`
2. **อัปเดตข้อมูลสรุปรายปี** - อัปเดตข้อมูลสรุปรายปีของแบบประเมิน

---

## Scheduled Tasks ที่มี

### 1. `surveys:update-expired`
- **คำอธิบาย**: อัปเดตสถานะแบบประเมินที่หมดอายุเป็น `expired`
- **เวลา**: ทุกวันเวลา 00:00 (เวลาไทย)
- **Timezone**: `Asia/Bangkok`
- **ไฟล์**: `app/Console/Commands/UpdateExpiredSurveys.php`

### 2. `surveys:update-annual-summaries`
- **คำอธิบาย**: อัปเดตข้อมูลสรุปรายปีของแบบประเมิน
- **เวลา**: ทุกวันเวลา 01:00 (เวลาไทย)
- **Timezone**: `Asia/Bangkok`
- **ไฟล์**: `app/Console/Commands/UpdateAnnualSummaries.php`

---

## การตั้งค่า

### 1. ไฟล์ Configuration

Scheduled Tasks ถูกกำหนดในไฟล์ `routes/console.php`:

```php
// กำหนดการตรวจสอบแบบประเมินที่หมดอายุ
Schedule::command('surveys:update-expired')
    ->daily()
    ->at('00:00')
    ->timezone('Asia/Bangkok')
    ->name('update-expired-surveys')
    ->description('อัปเดตสถานะแบบประเมินที่หมดอายุ');

// กำหนดการอัพเดทข้อมูลสรุปรายปี
Schedule::command('surveys:update-annual-summaries')
    ->daily()
    ->at('01:00')
    ->timezone('Asia/Bangkok')
    ->name('update-annual-summaries')
    ->description('อัปเดตข้อมูลสรุปรายปีของแบบประเมิน');
```

### 2. Timezone Configuration

⚠️ **สำคัญ**: ต้องระบุ `->timezone('Asia/Bangkok')` เพื่อให้ตรงกับเวลาไทย

- **Laravel default timezone**: `UTC` (ใน `config/app.php`)
- **Timezone ที่ใช้ใน Scheduled Tasks**: `Asia/Bangkok` (+07:00)

---

## การทดสอบ

### 1. ดู Scheduled Tasks ทั้งหมด

```bash
php artisan schedule:list
```

ผลลัพธ์:
```
  0 0 * * *  php artisan surveys:update-expired
  0 1 * * *  php artisan surveys:update-annual-summaries
```

### 2. รัน Command โดยตรง (ทดสอบทันที)

```bash
php artisan surveys:update-expired
```

### 3. รัน Scheduled Tasks ที่ถึงเวลาแล้ว

```bash
php artisan schedule:run
```

คำสั่งนี้จะรันเฉพาะ tasks ที่ถึงเวลาแล้วเท่านั้น

### 4. รัน Scheduler แบบ Watch (สำหรับ Development)

```bash
php artisan schedule:work
```

คำสั่งนี้จะ:
- ตรวจสอบทุก 1 นาทีว่า tasks ถึงเวลาแล้วหรือยัง
- รัน tasks ที่ถึงเวลาแล้วอัตโนมัติ
- เหมาะสำหรับทดสอบใน Development

**วิธีหยุด**: กด `Ctrl + C`

### 5. ทดสอบด้วยการเปลี่ยนเวลา

เพื่อทดสอบได้เร็วขึ้น สามารถเปลี่ยนเวลาใน `routes/console.php` เป็นเวลาปัจจุบัน:

```php
// ตัวอย่าง: เปลี่ยนเป็น 18:20 เพื่อทดสอบตอน 18:20
Schedule::command('surveys:update-expired')
    ->daily()
    ->at('18:20')  // เปลี่ยนเวลาตามต้องการ
    ->timezone('Asia/Bangkok')
    ->name('update-expired-surveys')
    ->description('อัปเดตสถานะแบบประเมินที่หมดอายุ');
```

จากนั้นรัน:
```bash
php artisan schedule:work
```

⚠️ **อย่าลืมเปลี่ยนกลับเป็นเวลาเดิมหลังจากทดสอบเสร็จ**

---

## การใช้งานใน Production

### 1. ตั้งค่า Cron Job

สำหรับ Production ต้องตั้งค่า Cron Job เพื่อให้ Laravel Scheduler ทำงานอัตโนมัติ

⚠️ **สำคัญ**: ต้องใช้ **full path** ของ PHP ใน cron job เพื่อให้ cron หา PHP ได้

#### ขั้นตอนที่ 1: หา PHP Path บน Production Server

```bash
# หา path ของ PHP
which php

# หรือ
whereis php

# ตรวจสอบ PHP version
php -v
```

**ตัวอย่างผลลัพธ์**:
- `/usr/bin/php`
- `/opt/php/bin/php`
- `/usr/local/bin/php`

#### ขั้นตอนที่ 2: หา Project Path

```bash
# ตรวจสอบว่าโปรเจคอยู่ที่ไหน
pwd

# หรือ
ls -la /var/www/
```

**ตัวอย่าง path**:
- `/var/www/satisfaction-survey`
- `/home/user/satisfaction-survey`
- `/opt/satisfaction-survey`

#### ขั้นตอนที่ 3: เปิดไฟล์ Crontab

```bash
crontab -e
```

#### ขั้นตอนที่ 4: เพิ่ม Cron Job

เพิ่มบรรทัดนี้ (ใช้ **full path** ของ PHP):

```bash
* * * * * cd /path-to-your-project && /full/path/to/php artisan schedule:run >> /dev/null 2>&1
```

**ตัวอย่าง** (ปรับ path ให้ตรงกับ production server ของคุณ):

```bash
# ตัวอย่างที่ 1: Linux Server (Ubuntu/Debian)
* * * * * cd /var/www/satisfaction-survey && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

# ตัวอย่างที่ 2: Linux Server (CentOS/RHEL)
* * * * * cd /var/www/html/satisfaction-survey && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1

# ตัวอย่างที่ 3: macOS (Development)
* * * * * cd /Applications/XAMPP/xamppfiles/htdocs/satisfaction-survey && /opt/homebrew/bin/php artisan schedule:run >> /dev/null 2>&1
```

#### ขั้นตอนที่ 5: บันทึกและออก

- กด `Esc` แล้วพิมพ์ `:wq` (สำหรับ vi/vim)
- หรือกด `Ctrl + X` แล้วกด `Y` (สำหรับ nano)

#### ขั้นตอนที่ 6: ตรวจสอบ Cron Job

```bash
# ตรวจสอบ cron job ที่ตั้งค่าไว้
crontab -l

# ตรวจสอบ scheduled tasks
cd /path-to-your-project
php artisan schedule:list
```

#### ขั้นตอนที่ 7: ทดสอบ Cron Job

```bash
# ทดสอบรัน schedule:run โดยตรง
cd /path-to-your-project
php artisan schedule:run

# ตรวจสอบ logs
tail -f storage/logs/laravel.log
```

### 2. ตรวจสอบว่า Cron Job ทำงาน

```bash
# ดู logs ของ cron (Linux)
grep CRON /var/log/syslog

# หรือสำหรับ macOS
grep CRON /var/log/system.log

# ตรวจสอบว่า cron service ทำงานอยู่
systemctl status cron

# หรือ
service cron status
```

### 3. ใช้ Supervisor (แนะนำสำหรับ Production)

สำหรับ Production ที่ต้องการความเสถียรมากกว่า แนะนำให้ใช้ Supervisor เพื่อรัน `schedule:work` แทน cron job

#### ขั้นตอนที่ 1: ติดตั้ง Supervisor

```bash
# Ubuntu/Debian
sudo apt-get install supervisor

# CentOS/RHEL
sudo yum install supervisor
```

#### ขั้นตอนที่ 2: สร้าง Supervisor Config

```bash
sudo nano /etc/supervisor/conf.d/satisfaction-survey-scheduler.conf
```

#### ขั้นตอนที่ 3: เพิ่ม Configuration

```ini
[program:satisfaction-survey-scheduler]
process_name=%(program_name)s
command=/usr/bin/php /var/www/satisfaction-survey/artisan schedule:work
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/satisfaction-survey/storage/logs/scheduler.log
stopwaitsecs=3600
```

**หมายเหตุ**: ปรับ path ให้ตรงกับ production server ของคุณ

#### ขั้นตอนที่ 4: Reload Supervisor

```bash
# อ่าน config ใหม่
sudo supervisorctl reread

# อัปเดต supervisor
sudo supervisorctl update

# เริ่ม service
sudo supervisorctl start satisfaction-survey-scheduler

# ตรวจสอบสถานะ
sudo supervisorctl status
```

#### ขั้นตอนที่ 5: ตรวจสอบ Logs

```bash
# ดู logs ของ supervisor
tail -f /var/www/satisfaction-survey/storage/logs/scheduler.log

# ดู logs ของ Laravel
tail -f /var/www/satisfaction-survey/storage/logs/laravel.log
```

---

## Production Checklist

ก่อน deploy ไป production ตรวจสอบรายการต่อไปนี้:

- [ ] หา PHP path บน production server: `which php`
- [ ] หา project path: `pwd` หรือ `ls -la`
- [ ] ตั้งค่า cron job: `crontab -e`
- [ ] ใช้ full path ของ PHP ใน cron job
- [ ] ตรวจสอบ cron job: `crontab -l`
- [ ] ทดสอบ schedule:run: `php artisan schedule:run`
- [ ] ตรวจสอบ scheduled tasks: `php artisan schedule:list`
- [ ] ตรวจสอบ logs: `tail -f storage/logs/laravel.log`
- [ ] ตรวจสอบ timezone ใน `routes/console.php`: ต้องมี `->timezone('Asia/Bangkok')`
- [ ] ตรวจสอบว่า cron service ทำงาน: `systemctl status cron`
- [ ] (ถ้าใช้ Supervisor) ติดตั้งและตั้งค่า Supervisor
- [ ] (ถ้าใช้ Supervisor) ตรวจสอบสถานะ: `supervisorctl status`

---

## การตรวจสอบ Logs

### 1. ดู Logs ล่าสุด

```bash
tail -f storage/logs/laravel.log
```

### 2. ค้นหา Logs ของ Scheduled Task

```bash
grep "Scheduled Task" storage/logs/laravel.log
```

### 3. ตัวอย่าง Logs

เมื่อ Scheduled Task ทำงาน จะเห็น logs แบบนี้:

```
[2025-11-01 00:00:00] local.INFO: 🔔 Scheduled Task: surveys:update-expired เริ่มทำงาน {"timestamp":"2025-11-01 00:00:00","timezone":"UTC"}
[2025-11-01 00:00:00] local.INFO: อัปเดตสถานะแบบประเมินเป็น expired {"invitation_id":178,"survey_id":32,"customer_id":35}
[2025-11-01 00:00:00] local.INFO: ✅ Scheduled Task: surveys:update-expired เสร็จสิ้น {"updated_count":1}
```

### 4. ดู Logs เฉพาะวันนี้

```bash
grep "$(date +%Y-%m-%d)" storage/logs/laravel.log | grep "Scheduled Task"
```

---

## การแก้ไขปัญหา

### ปัญหา 1: Scheduled Task ไม่ทำงาน

**สาเหตุที่เป็นไปได้:**
- Cron Job ไม่ได้ตั้งค่า
- Timezone ไม่ตรงกัน
- Command ผิดพลาด

**วิธีแก้:**
1. ตรวจสอบ Cron Job: `crontab -l`
2. ตรวจสอบ Timezone ใน `routes/console.php`: ต้องมี `->timezone('Asia/Bangkok')`
3. ทดสอบรัน command โดยตรง: `php artisan surveys:update-expired`
4. ตรวจสอบ logs: `tail -f storage/logs/laravel.log`

### ปัญหา 2: เวลาไม่ตรงกัน

**สาเหตุ:** Timezone ไม่ตรงกันระหว่าง Laravel (UTC) กับระบบ (Asia/Bangkok)

**วิธีแก้:**
เพิ่ม `->timezone('Asia/Bangkok')` ใน `routes/console.php`:

```php
Schedule::command('surveys:update-expired')
    ->daily()
    ->at('00:00')
    ->timezone('Asia/Bangkok')  // ← เพิ่มบรรทัดนี้
    ->name('update-expired-surveys');
```

### ปัญหา 3: Status ไม่ถูกอัปเดต

**สาเหตุที่เป็นไปได้:**
- ไม่มีแบบประเมินที่หมดอายุ
- Status ไม่ใช่ `'sent'` (อาจเป็น `'completed'` หรืออื่นๆ)
- Query ไม่ถูกต้อง

**วิธีตรวจสอบ:**
```bash
php artisan tinker --execute="
use App\Models\SurveyInvitation;
\$expired = SurveyInvitation::where('expires_at', '<', now())
    ->whereIn('status', ['sent'])
    ->get();
echo 'Found: ' . \$expired->count() . ' expired surveys\n';
"
```

### ปัญหา 4: `schedule:work` ไม่ทำงาน

**วิธีแก้:**
1. ตรวจสอบว่าไม่มี process อื่นรันอยู่: `ps aux | grep schedule`
2. ลองรันใหม่: `php artisan schedule:work`
3. ตรวจสอบ logs: `tail -f storage/logs/laravel.log`

### ปัญหา 5: Cron Job ไม่ทำงาน (PHP: command not found)

**สาเหตุ:** Cron environment ไม่มี PHP ใน PATH

**วิธีแก้:**
1. ใช้ **full path** ของ PHP ใน cron job:
   ```bash
   # ❌ ผิด
   * * * * * cd /var/www/satisfaction-survey && php artisan schedule:run
   
   # ✅ ถูก
   * * * * * cd /var/www/satisfaction-survey && /usr/bin/php artisan schedule:run
   ```

2. หา PHP path:
   ```bash
   which php
   ```

3. ตรวจสอบ cron job:
   ```bash
   crontab -l
   ```

### ปัญหา 6: Cron Job ไม่ทำงาน (Permission denied)

**สาเหตุ:** User ที่รัน cron ไม่มีสิทธิ์เข้าถึงไฟล์

**วิธีแก้:**
1. ตรวจสอบ user ที่รัน cron:
   ```bash
   whoami
   ```

2. ตรวจสอบสิทธิ์ของไฟล์:
   ```bash
   ls -la /path-to-project/artisan
   ```

3. เปลี่ยน owner หรือเพิ่มสิทธิ์:
   ```bash
   sudo chown -R www-data:www-data /var/www/satisfaction-survey
   sudo chmod -R 755 /var/www/satisfaction-survey
   ```

### ปัญหา 7: Scheduled Tasks ไม่ทำงานตามเวลา

**สาเหตุที่เป็นไปได้:**
- Timezone ไม่ตรงกัน
- Cron job ไม่ทำงาน
- Server time ไม่ถูกต้อง

**วิธีแก้:**
1. ตรวจสอบ timezone ใน `routes/console.php`: ต้องมี `->timezone('Asia/Bangkok')`
2. ตรวจสอบ server time:
   ```bash
   date
   timedatectl status
   ```
3. ตรวจสอบ cron job: `crontab -l`
4. ทดสอบ schedule:run: `php artisan schedule:run`

---

## ข้อมูลเพิ่มเติม

### คำสั่งที่เกี่ยวข้อง

| คำสั่ง | คำอธิบาย |
|--------|----------|
| `php artisan schedule:list` | แสดง scheduled tasks ทั้งหมด |
| `php artisan schedule:run` | รัน tasks ที่ถึงเวลาแล้ว (ครั้งเดียว) |
| `php artisan schedule:work` | รัน scheduler แบบ watch (ทุกนาที) |
| `php artisan surveys:update-expired` | รัน command โดยตรง |
| `php artisan surveys:update-annual-summaries` | รัน command โดยตรง |

### ไฟล์ที่เกี่ยวข้อง

- `routes/console.php` - กำหนด scheduled tasks
- `app/Console/Commands/UpdateExpiredSurveys.php` - Command ตรวจสอบวันหมดอายุ
- `app/Console/Commands/UpdateAnnualSummaries.php` - Command อัปเดตสรุปรายปี
- `storage/logs/laravel.log` - Logs ของระบบ

### Timezone Reference

- **Asia/Bangkok**: UTC+07:00 (เวลาไทย)
- **UTC**: Coordinated Universal Time

### Best Practices

1. ✅ **ระบุ Timezone** ใน scheduled tasks เสมอ
2. ✅ **เพิ่ม Logging** เพื่อตรวจสอบการทำงาน
3. ✅ **ทดสอบก่อน** deploy ไป production
4. ✅ **ตั้งค่า Cron Job** สำหรับ production
5. ✅ **ตรวจสอบ Logs** เป็นประจำ

---

## ติดต่อและสนับสนุน

หากพบปัญหาหรือมีคำถาม กรุณาตรวจสอบ:
1. Logs: `storage/logs/laravel.log`
2. Documentation: Laravel Scheduler Documentation
3. PHP Timezone List: https://www.php.net/manual/en/timezones.asia.php

---

**อัปเดตล่าสุด**: 2025-11-10
**เวอร์ชัน**: 1.1

---

## หมายเหตุสำหรับ Production Deployment

### ⚠️ สิ่งที่ต้องทำเมื่อ Deploy ไป Production:

1. **ตั้งค่า Cron Job ใหม่** - Cron job ที่ตั้งไว้ใน development จะไม่อยู่ใน production server
2. **หา PHP Path** - ใช้ `which php` เพื่อหา full path ของ PHP
3. **หา Project Path** - ตรวจสอบว่าโปรเจคอยู่ที่ไหนบน production server
4. **ใช้ Full Path** - ใช้ full path ของ PHP ใน cron job
5. **ตรวจสอบ Timezone** - ตรวจสอบว่า timezone ใน `routes/console.php` ถูกต้อง
6. **ทดสอบ** - ทดสอบรัน `schedule:run` และตรวจสอบ logs

### 📝 ตัวอย่าง Cron Job สำหรับ Production:

```bash
# ตรวจสอบ PHP path
which php
# ผลลัพธ์: /usr/bin/php

# ตรวจสอบ project path
pwd
# ผลลัพธ์: /var/www/satisfaction-survey

# ตั้งค่า cron job
crontab -e

# เพิ่มบรรทัดนี้:
* * * * * cd /var/www/satisfaction-survey && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

# ตรวจสอบ
crontab -l

# ทดสอบ
cd /var/www/satisfaction-survey
/usr/bin/php artisan schedule:run
```

