# Laravel Scheduler untuk Unreviewed Status dengan Email Reminder

## Overview
Sistem ini menggunakan Laravel Scheduler untuk mengelola deadline approval dan secara otomatis:
1. Mengirim email reminder 24 jam sebelum deadline
2. Mengubah status menjadi "unreviewed" jika melewati batas waktu

Scheduler hanya berjalan pada hari kerja (Senin-Jumat) dan tidak menghitung hari Sabtu dan Minggu.

## Komponen Sistem

### 1. Database Columns (Migrations)

#### a. Migration: Deadline Columns
File: `database/migrations/2024_12_16_000001_add_deadline_columns_to_trs_so_document.php`

Kolom untuk tracking deadline:
- `temp_status_deadline` - Deadline untuk SPV/Head approval (2 hari kerja)
- `final_status_deadline` - Deadline untuk Manager approval (2 hari kerja)

#### b. Migration: Reminder Tracking
File: `database/migrations/2024_12_17_000001_add_reminder_sent_columns_to_trs_so_document.php`

Kolom untuk tracking apakah reminder sudah dikirim:
- `temp_reminder_sent` - Flag reminder SPV/Head (boolean)
- `final_reminder_sent` - Flag reminder Manager (boolean)

### 2. Helper Function
File: `app/Helpers/Function_Helper.php`

Fungsi `addBusinessDays($startDate, $days)`:
- Menghitung hari kerja dengan tidak menghitung Sabtu dan Minggu
- Digunakan untuk set deadline

### 3. Email System

#### a. Mailable Class
File: `app/Mail/ApprovalReminderMail.php`

Class untuk mengirim email reminder dengan data:
- Document details
- User information
- Approval type (temp/final)
- Deadline date
- URL to document

#### b. Email Template
File: `resources/views/emails/approval-reminder.blade.php`

Template email HTML dengan:
- Company name "PT Multi Spunindo Jaya Tbk" di header
- Informasi dokumen yang pending
- Deadline warning (highlighted)
- Tombol "View & Approve Document"
- Professional styling dengan color contrast yang baik
- **Note:** Logo tidak disertakan karena attachment issues di email clients

### 4. Command untuk Check Deadline & Send Reminder
File: `app/Console/Commands/CheckUnreviewedDeadline.php`

Command: `php artisan so:check-unreviewed-deadline`

Fungsi:
1. **Send Reminder Emails (24 jam sebelum deadline)**
   - Cek dokumen yang deadline-nya 24 jam lagi
   - Kirim email ke user yang belum approve
   - Mark reminder_sent = true

2. **Update Unreviewed Status**
   - Mengecek dokumen yang deadline-nya sudah lewat
   - Update `temp_status` menjadi "unreviewed" jika SPV/Head terlambat
   - Update `final_status` menjadi "unreviewed" jika Manager terlambat
   - Otomatis set deadline berikutnya

### 5. Scheduler Configuration
File: `app/Console/Kernel.php`

```php
$schedule->command('so:check-unreviewed-deadline')
    ->hourly()
    ->weekdays()
    ->timezone('Asia/Jakarta');
```

Scheduler berjalan:
- Setiap jam
- Hanya hari kerja (Senin-Jumat)
- Timezone: Asia/Jakarta

### 6. Controller Updates
File: `app/Http/Controllers/TrsapvController.php`

#### a. Method `sendData()`
- Set `temp_status_deadline` = 2 hari kerja dari sekarang
- Set `temp_reminder_sent` = false
- Saat admin mengirim data untuk approval

#### b. Method `approval()`
- Jika SPV/Head approve:
  - Set `final_status_deadline` = 2 hari kerja dari sekarang
  - Set `final_reminder_sent` = false

#### c. Method `recall()`
- Reset deadline dan reminder flags saat recall
- Clear semua tracking columns

## Cara Kerja

### Flow Deadline & Email:

1. **Admin Send Data (Day 0)**
   - Admin mengirim data ke SPV/Head
   - System set `temp_status_deadline` = sekarang + 2 hari kerja
   - Status: `temp_status = 'pending'`
   - `temp_reminder_sent = false`

2. **Email Reminder (Day 1 - 24 hours before deadline)**
   - Scheduler cek apakah sudah 24 jam sebelum deadline
   - Jika `temp_reminder_sent = false`, kirim email ke SPV/Head
   - Email berisi:
     - Logo perusahaan
     - Detail dokumen
     - Deadline warning
     - Tombol redirect ke `/trsapv/show/{id}`
   - Set `temp_reminder_sent = true`

3. **SPV/Head Approval (Within Day 2)**
   - **Scenario A: Approve dalam waktu**
     - `temp_status = 'approved'`
     - System set `final_status_deadline` = sekarang + 2 hari kerja
     - `final_reminder_sent = false`
   
   - **Scenario B: Melewati deadline**
     - Scheduler otomatis ubah `temp_status = 'unreviewed'`
     - System set `final_status_deadline` = sekarang + 2 hari kerja

4. **Manager Email Reminder (Day 3 - 24 hours before final deadline)**
   - Scheduler kirim email ke Manager
   - Set `final_reminder_sent = true`

5. **Manager Approval (Within Day 4)**
   - **Scenario A: Approve dalam waktu**
     - `final_status = 'approved'`
   
   - **Scenario B: Melewati deadline**
     - Scheduler otomatis ubah `final_status = 'unreviewed'`

### Email Content Details:

**Subject:** Reminder: Pending Approval - Sales Order Document

**Body includes:**
- Company name (PT Multi Spunindo Jaya Tbk) di header
- Personal greeting dengan nama user
- Document ID dan approval type
- Deadline date (format: Senin, 17 Desember 2024 15:00)
- Warning box dengan countdown
- Call-to-action button dengan text yang jelas (white text on teal button)
- Alternative text link jika button tidak bekerja
- URL otomatis menggunakan APP_URL dari config

### Perhitungan Hari Kerja:

Sabtu dan Minggu tidak dihitung dalam deadline:
- **Kirim Kamis jam 10:00**
  - Reminder: Jumat jam 10:00 (1 hari kerja)
  - Deadline: Senin jam 10:00 (2 hari kerja)

- **Kirim Jumat jam 15:00**
  - Reminder: Senin jam 15:00 (skip weekend)
  - Deadline: Selasa jam 15:00 (skip weekend)

- Scheduler hanya berjalan Senin-Jumat

## Setup di Server

### 1. Jalankan Migration
```bash
php artisan migrate
```

Ini akan menambahkan 4 kolom baru:
- temp_status_deadline
- final_status_deadline
- temp_reminder_sent
- final_reminder_sent

### 2. Konfigurasi Email di .env
```env
# Application URL (penting untuk email links)
APP_URL=https://your-domain.com

# Email Configuration
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=your-email@gmail.com
MAIL_FROM_NAME="PT Multi Spunindo Jaya Tbk"
```

**Penting:** Pastikan `APP_URL` di-set dengan domain production yang benar, bukan localhost!

### 3. Pastikan Config Cache Ter-update
```bash
php artisan config:cache
```

### 4. Setup Cron Job di Server
Tambahkan ke crontab:
```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

### 5. Test Email Configuration
```bash
php artisan tinker
```
```php
Mail::raw('Test email', function($message) {
    $message->to('test@example.com')->subject('Test');
});
```

### 6. Test Command Manual
```bash
php artisan so:check-unreviewed-deadline
```

### 7. Check Scheduler List
```bash
php artisan schedule:list
```

## Testing

### 1. Test Command Langsung
```bash
php artisan so:check-unreviewed-deadline
```

Output:
```
Temp reminder sent for document #123
Final reminder sent for document #124
Deadline check completed. Temp: 0, Final: 0
```

### 2. Test Email Template
Buat test route sementara di `routes/web.php`:
```php
Route::get('/test-email', function() {
    $document = (object)['id' => 123];
    $user = (object)['name' => 'John Doe', 'email' => 'test@example.com'];
    $deadlineDate = now()->addDays(1);
    $showUrl = url('/trsapv/show/' . encrypt(123));
    
    return new App\Mail\ApprovalReminderMail($document, $user, 'temp', $deadlineDate, $showUrl);
});
```

Akses: `http://localhost:8000/test-email`

### 3. Test dengan Data Dummy
Buat dokumen dengan deadline mendekati untuk testing.

## Monitoring

### Log Location
File: `storage/logs/laravel.log`

Log akan mencatat:
- Email yang berhasil dikirim
- Email yang gagal dikirim
- Dokumen yang diupdate menjadi unreviewed
- Error yang terjadi

### Check Log Command:
```bash
tail -f storage/logs/laravel.log
```

### Email Logs Examples:
```
[2024-12-17 10:00:00] Reminder email sent to john@example.com for document ID 123 (temp approval)
[2024-12-17 10:00:00] Reminder email sent to manager@example.com for document ID 124 (final approval)
[2024-12-17 15:00:00] Document ID 125 temp_status set to unreviewed (deadline passed)
```

## Troubleshooting

### Email Tidak Terkirim

**1. Check SMTP Configuration**
```bash
php artisan config:cache
php artisan tinker
```
```php
config('mail.mailers.smtp');
```

**2. Check User Email**
Pastikan users memiliki email valid di database:
```sql
SELECT id, username, email FROM users WHERE email IS NOT NULL;
```

**3. Check Mail Queue**
Jika menggunakan queue:
```bash
php artisan queue:work
```

**4. Test SMTP Connection**
```bash
telnet smtp.gmail.com 587
```

### Reminder Tidak Dikirim

**1. Check reminder_sent Flag**
```sql
SELECT id, temp_status, temp_reminder_sent, temp_status_deadline 
FROM trs_so_document 
WHERE temp_status = 'pending';
```

**2. Check Deadline Calculation**
Pastikan deadline dihitung dengan benar (exclude weekend)

**3. Manual Reset Reminder Flag**
```sql
UPDATE trs_so_document 
SET temp_reminder_sent = 0 
WHERE id = 123;
```

### Logo Tidak Muncul di Email

Logo telah dihapus dari template karena masalah rendering di email clients. Sebagai gantinya, company name ditampilkan sebagai text di header.

### URL Mengarah ke Localhost

**1. Set APP_URL di .env**
```env
APP_URL=https://your-production-domain.com
```

**2. Clear Config Cache**
```bash
php artisan config:cache
```

**3. Verify APP_URL**
```bash
php artisan tinker
```
```php
config('app.url');
url('/trsapv/show/123');
```

**4. Test Email dengan URL yang Benar**
System menggunakan `url()` helper yang otomatis membaca APP_URL dari config.

### Scheduler Tidak Berjalan

**1. Check Cron Job**
```bash
crontab -l
```

**2. Check Cron Logs**
```bash
grep CRON /var/log/syslog
```

**3. Manual Test**
```bash
php artisan schedule:run
```

## Email Template Customization

Edit file: `resources/views/emails/approval-reminder.blade.php`

### Ubah Warna Brand
```css
.email-header {
    background-color: #0056b3; /* Ganti dengan warna brand */
}
```

### Tambah Informasi
Tambahkan data di Mailable constructor dan tampilkan di view:
```php
// ApprovalReminderMail.php
public $customField;

// approval-reminder.blade.php
{{ $customField }}
```

### Multiple Recipients
Edit command untuk CC/BCC:
```php
Mail::to($user->email)
    ->cc('manager@example.com')
    ->send(new ApprovalReminderMail(...));
```

## Migration Rollback

Jika perlu rollback:
```bash
# Rollback reminder columns
php artisan migrate:rollback --step=1

# Rollback deadline columns
php artisan migrate:rollback --step=1
```

Ini akan menghapus semua kolom yang ditambahkan.

## Performance Considerations

### Batch Processing
Jika dokumen banyak, pertimbangkan batch processing:
```php
$tempReminders->chunk(100, function($documents) {
    foreach($documents as $document) {
        // Send email
    }
});
```

### Queue Emails
Untuk performa lebih baik, queue emails:
```php
// ApprovalReminderMail.php
class ApprovalReminderMail extends Mailable implements ShouldQueue
{
    // ...
}
```

Jalankan queue worker:
```bash
php artisan queue:work
```

## Security Notes

1. **Email Encryption**: Gunakan TLS/SSL untuk SMTP
2. **Rate Limiting**: Pertimbangkan rate limit untuk email
3. **URL Encryption**: ID dokumen sudah di-encrypt untuk security
4. **Email Validation**: Pastikan email valid sebelum kirim

## Summary Timeline

| Event | Timing | Action |
|-------|--------|--------|
| Admin Send | Day 0 | Set deadline = +2 hari kerja |
| SPV Reminder | Day 1 (24h before) | Email ke SPV/Head |
| SPV Deadline | Day 2 | Auto unreviewed jika tidak approve |
| Manager Reminder | Day 3 (24h before) | Email ke Manager |
| Manager Deadline | Day 4 | Auto unreviewed jika tidak approve |

*Note: Weekend (Sabtu-Minggu) tidak dihitung*

## Komponen Sistem

### 1. Database Columns (Migration)
File: `database/migrations/2024_12_16_000001_add_deadline_columns_to_trs_so_document.php`

Menambahkan 2 kolom baru pada tabel `trs_so_document`:
- `temp_status_deadline` - Deadline untuk SPV/Head approval
- `final_status_deadline` - Deadline untuk Manager approval

### 2. Helper Function
File: `app/Helpers/Function_Helper.php`

Fungsi `addBusinessDays($startDate, $days)`:
- Menghitung hari kerja dengan tidak menghitung Sabtu dan Minggu
- Digunakan untuk set deadline

### 3. Command untuk Check Deadline
File: `app/Console/Commands/CheckUnreviewedDeadline.php`

Command: `php artisan so:check-unreviewed-deadline`

Fungsi:
- Mengecek dokumen yang deadline-nya sudah lewat
- Mengupdate `temp_status` menjadi "unreviewed" jika SPV/Head terlambat approve
- Mengupdate `final_status` menjadi "unreviewed" jika Manager terlambat approve
- Secara otomatis set `final_status_deadline` ketika temp_status menjadi unreviewed

### 4. Scheduler Configuration
File: `app/Console/Kernel.php`

```php
$schedule->command('so:check-unreviewed-deadline')
    ->hourly()
    ->weekdays()
    ->timezone('Asia/Jakarta');
```

Scheduler berjalan:
- Setiap jam
- Hanya hari kerja (Senin-Jumat)
- Timezone: Asia/Jakarta

### 5. Controller Updates
File: `app/Http/Controllers/TrsapvController.php`

#### a. Method `sendData()`
- Set `temp_status_deadline` = 1 hari kerja dari sekarang
- Saat admin mengirim data untuk approval

#### b. Method `approval()`
- Jika SPV/Head approve, set `final_status_deadline` = 1 hari kerja dari sekarang
- Menghapus dispatch Job `UnreviewedAfterTimePeriod` (tidak digunakan lagi)

#### c. Method `recall()`
- Reset deadline saat recall dilakukan
- Clear `temp_status_deadline` atau `final_status_deadline`

## Cara Kerja

### Flow Deadline:

1. **Admin Send Data**
   - Admin mengirim data ke SPV/Head
   - System set `temp_status_deadline` = sekarang + 1 hari kerja
   - Status: `temp_status = 'pending'`

2. **SPV/Head Approval**
   - Jika SPV/Head approve dalam waktu 1 hari kerja:
     - `temp_status = 'approved'`
     - System set `final_status_deadline` = sekarang + 1 hari kerja
   - Jika melewati deadline:
     - Scheduler otomatis ubah `temp_status = 'unreviewed'`
     - System set `final_status_deadline` = sekarang + 1 hari kerja

3. **Manager Approval**
   - Jika Manager approve dalam waktu 1 hari kerja:
     - `final_status = 'approved'`
   - Jika melewati deadline:
     - Scheduler otomatis ubah `final_status = 'unreviewed'`

### Perhitungan Hari Kerja:

Sabtu dan Minggu tidak dihitung dalam deadline:
- Jika send Jumat jam 15:00, deadline Senin jam 15:00 (bukan Sabtu)
- Jika send Kamis jam 10:00, deadline Jumat jam 10:00
- Scheduler hanya berjalan Senin-Jumat

## Setup di Server

### 1. Jalankan Migration
```bash
php artisan migrate
```

### 2. Setup Cron Job di Server
Tambahkan ke crontab:
```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

Cron ini akan menjalankan Laravel scheduler setiap menit, dan scheduler akan menjalankan command sesuai jadwal yang ditentukan (hourly pada weekdays).

### 3. Test Command Manual
```bash
php artisan so:check-unreviewed-deadline
```

### 4. Check Scheduler List
```bash
php artisan schedule:list
```

## Monitoring

### Log Location
File: `storage/logs/laravel.log`

Log akan mencatat:
- Setiap dokumen yang diupdate menjadi unreviewed
- Error yang terjadi saat menjalankan command

### Check Log Command:
```bash
php artisan so:check-unreviewed-deadline
```

Output:
```
Deadline check completed. Temp: X, Final: Y
```
- X = jumlah dokumen temp_status yang diupdate
- Y = jumlah dokumen final_status yang diupdate

## Troubleshooting

### Scheduler Tidak Berjalan
1. Cek cron job sudah terpasang
2. Pastikan timezone server sesuai
3. Check log: `tail -f storage/logs/laravel.log`

### Deadline Tidak Tepat
1. Cek timezone di `config/app.php`
2. Cek fungsi `addBusinessDays()` di Function_Helper
3. Pastikan scheduler berjalan dengan `schedule:list`

## Migration Rollback

Jika perlu rollback:
```bash
php artisan migrate:rollback --step=1
```

Ini akan menghapus kolom `temp_status_deadline` dan `final_status_deadline`.
