# Deployment Steps: Special Access Priority Ordering

## ⚠️ IMPORTANT: Deployment Required

The changes made to prioritize special access products are in your **LOCAL development environment only**. You need to deploy these changes to your **production server** (apps.appliedhe.one) for them to take effect.

## Files Modified

**1. `api.php`** - Main file with ordering logic changes
   - Modified lines: 720-770
   - Added special access priority flag
   - Changed ORDER BY clause

## Deployment Steps

### Option 1: Deploy via Git (Recommended)

```bash
# 1. Commit the changes
git add api.php
git commit -m "feat: prioritize special access products in ordering"

# 2. Push to repository
git push origin homepc

# 3. On production server, pull the changes
# SSH into: apps.appliedhe.one
cd /path/to/xchange_reg
git pull origin homepc

# 4. Clear any PHP opcache if enabled
# (check with your hosting provider)
```

### Option 2: Manual FTP/SFTP Upload

1. **Upload Modified File:**
   - Source: `C:\xampp\htdocs\Xchange_Admin\api.php`
   - Destination: `apps.appliedhe.one/xchange_reg/api.php`

2. **Verify Upload:**
   - Check file timestamp matches
   - File size should be similar

3. **Clear Cache:**
   - Clear browser cache (Ctrl+Shift+Del)
   - Clear server-side cache if any

### Option 3: Copy-Paste Code Changes

If you can't upload files, manually edit `api.php` on production:

**Find this section (around line 720):**

```php
$productQuery = "
    SELECT p.id, p.product_code, p.name, p.description, p.category_id, p.is_active, p.show_in_frontend,
           p.base_price, p.currency, p.total_stock, p.max_per_registration,
           pp.id as pricing_id, pp.pricing_tier, pp.price as tier_price, pp.valid_from, pp.valid_until, pp.is_active as pricing_active
    FROM products p
    LEFT JOIN product_pricing pp ON p.id = pp.product_id AND pp.is_active = 1
    WHERE p.is_active = 1 AND (";
```

**Replace with:**

```php
$productQuery = "
    SELECT p.id, p.product_code, p.name, p.description, p.category_id, p.is_active, p.show_in_frontend,
           p.base_price, p.currency, p.total_stock, p.max_per_registration,
           pp.id as pricing_id, pp.pricing_tier, pp.price as tier_price, pp.valid_from, pp.valid_until, pp.is_active as pricing_active";

// Add special access priority flag if accessing via special link
if ($specialAccessLink && !empty($specialAccessProductIds)) {
    $placeholders = implode(',', array_fill(0, count($specialAccessProductIds), '?'));
    $productQuery .= ",
           CASE WHEN p.id IN ($placeholders) THEN 0 ELSE 1 END as is_special_access";
} else {
    $productQuery .= ",
           1 as is_special_access";
}

$productQuery .= "
    FROM products p
    LEFT JOIN product_pricing pp ON p.id = pp.product_id AND pp.is_active = 1
    WHERE p.is_active = 1 AND (";
```

**Then find the ORDER BY clause (around line 747):**

```php
$productQuery .= ") ORDER BY p.category_id, p.id, pp.valid_from ASC";
```

**Replace with:**

```php
// Order by: special access products first (0), then regular products (1), then by category and product ID
$productQuery .= ") ORDER BY is_special_access ASC, p.category_id, p.id, pp.valid_from ASC";
```

**Then find the execute section (around line 765):**

```php
if ($specialAccessLink && !empty($specialAccessProductIds)) {
    $stmt->execute($specialAccessProductIds);
} else {
    $stmt->execute();
}
```

**Replace with:**

```php
// Bind parameters if we have special access products
// Need to pass IDs twice: once for CASE statement, once for WHERE clause
if ($specialAccessLink && !empty($specialAccessProductIds)) {
    // Combine the arrays: first for CASE statement, second for WHERE clause
    $executeParams = array_merge($specialAccessProductIds, $specialAccessProductIds);
    $stmt->execute($executeParams);
} else {
    $stmt->execute();
}
```

**Finally, find the product array creation (around line 810):**

```php
$productsByCategory[$categoryId][$productId] = [
    'id' => $row['id'],
    'product_code' => $row['product_code'],
    'name' => $row['name'],
    'description' => $row['description'],
    'category_id' => $row['category_id'],
    'is_active' => $row['is_active'],
    'base_price' => (float)$row['base_price'],
    'currency' => $row['currency'],
    'total_stock' => $row['total_stock'],
    'max_per_registration' => $row['max_per_registration'],
    'default_tier_name' => isset($defaultTierNames[$productId]) ? $defaultTierNames[$productId] : null,
    'pricing_tiers' => []
];
```

**Add this line after `default_tier_name`:**

```php
'default_tier_name' => isset($defaultTierNames[$productId]) ? $defaultTierNames[$productId] : null,
'is_special_access' => ($row['is_special_access'] == 0), // true if from special access link
'pricing_tiers' => []
```

## Testing After Deployment

### Test on Production

1. **Access the special link:**
   ```
   https://apps.appliedhe.one/xchange_reg/index.html?access=SUNWAY-GUEST
   ```

2. **Verify Product Order:**
   - "Delegate Pass for Sunway Guests" should appear **FIRST**
   - Regular products should appear **AFTER**

3. **Run Debug Script (if uploaded):**
   ```
   https://apps.appliedhe.one/xchange_reg/debug_special_access.php?access=SUNWAY-GUEST
   ```

### Clear All Caches

After deployment:

1. **Browser Cache:**
   - Press `Ctrl + Shift + Del`
   - Clear cached images and files
   - Or use Incognito/Private mode

2. **Server Cache (if applicable):**
   - CloudFlare: Purge cache
   - Opcache: Restart PHP-FPM
   - CDN: Invalidate cache

3. **API Response Cache:**
   - Some servers cache API responses
   - May need to wait 5-10 minutes or restart web server

## Verification Checklist

- [ ] File `api.php` uploaded to production
- [ ] File size/timestamp matches local version
- [ ] Browser cache cleared
- [ ] Server cache cleared (if applicable)
- [ ] Access special link: `?access=SUNWAY-GUEST`
- [ ] Special products appear first
- [ ] Regular products appear after (if include_visible_products = true)
- [ ] Special access banner shows at top

## Troubleshooting

### Still Not Working After Deployment?

**1. Verify File Upload:**
```bash
# SSH into server and check file modification time
ls -la api.php
# Should show recent timestamp

# Check file contains new code
grep "is_special_access" api.php
# Should return results
```

**2. Check PHP Error Log:**
```bash
# Look for any PHP errors
tail -f /var/log/php-error.log
# or wherever your PHP errors are logged
```

**3. Test API Directly:**
```bash
# Access API directly with access code
curl "https://apps.appliedhe.one/xchange_reg/api.php?action=get_config&access=SUNWAY-GUEST"
```

**4. Verify Database:**
```sql
-- Check special access link exists
SELECT * FROM special_access_links 
WHERE link_code = 'SUNWAY-GUEST';

-- Check products configured in link
SELECT product_ids FROM special_access_links 
WHERE link_code = 'SUNWAY-GUEST';
```

## Local Testing (Current Environment)

Your local changes are working. Test locally:

```
http://localhost/Xchange_Admin/index.html?access=SUNWAY-GUEST
http://localhost/Xchange_Admin/debug_special_access.php?access=SUNWAY-GUEST
```

## Summary

🔴 **Current Situation:** You're viewing `apps.appliedhe.one` which doesn't have the changes yet

🟢 **Solution:** Deploy the modified `api.php` file to production server

📝 **Files to Deploy:**
- `api.php` (required)
- `debug_special_access.php` (optional, for debugging)
- `test_special_access_ordering.php` (optional, for testing)

Once deployed and caches cleared, special access products will appear first! 🎉

