# Pricing Simulation Implementation ✅

**Date:** February 11, 2026  
**Status:** IMPLEMENTED

---

## Overview

Implemented a flexible pricing simulation system that allows the portal to display estimated prices for packages that don't have fixed pricing (custom quotation packages). This is controlled via environment variables for easy testing and demo purposes.

---

## Problem Statement

Your real service packages (Magellan Metro-VPN, Shared Business Broadband, Dedicated Burst Internet, DIA, Dark Fibre, IPLC, InterCity-VPN) don't have fixed pricing because they require:
- Custom quotations based on location
- Distance-based calculations
- Bandwidth requirements
- Site surveys
- Custom enterprise needs

However, for **testing, demos, and UI development**, you need to show pricing to visualize the complete user experience.

---

## Solution

### Environment-Based Pricing Simulation

Added `.env` configuration flags that control whether packages show:
1. **Simulated pricing** (for testing/demo) - Shows estimated prices
2. **"Request Quote" only** (for production) - No pricing shown, quotation required

---

## Implementation Details

### 1. Environment Variables (.env)

```env
# =================== PRICING SIMULATION ===================
# Enable simulated pricing for packages without fixed prices (for demo/testing)
# When true: Packages will show estimated prices for UI testing
# When false: Packages without fixed pricing will show "Request Quote" only
SIMULATE_PACKAGE_PRICING=true

# Simulated pricing ranges (used when SIMULATE_PACKAGE_PRICING=true)
SIMULATE_MONTHLY_PRICE_MIN=50
SIMULATE_MONTHLY_PRICE_MAX=500
SIMULATE_INSTALLATION_FEE_MIN=100
SIMULATE_INSTALLATION_FEE_MAX=1000
```

### 2. Configuration (config/services.php)

```php
'pricing_simulation' => [
    'enabled' => env('SIMULATE_PACKAGE_PRICING', false),
    'monthly_price_min' => env('SIMULATE_MONTHLY_PRICE_MIN', 50),
    'monthly_price_max' => env('SIMULATE_MONTHLY_PRICE_MAX', 500),
    'installation_fee_min' => env('SIMULATE_INSTALLATION_FEE_MIN', 100),
    'installation_fee_max' => env('SIMULATE_INSTALLATION_FEE_MAX', 1000),
],
```

### 3. PricingSimulationService

Created `app/Services/PricingSimulationService.php` with intelligent pricing logic:

**Features:**
- Checks if simulation is enabled
- Only simulates packages without `has_fixed_pricing = true`
- Calculates prices based on package characteristics:
  - Package type (residential < business < enterprise)
  - Service category (feasibility_based, custom_enterprise, satellite)
  - Bandwidth requirements
  - Site survey requirements
  - Base price if available

**Methods:**
- `isEnabled()` - Check if simulation is on
- `applySimulatedPricing($package)` - Add simulated pricing to single package
- `applySimulatedPricingToCollection($packages)` - Process multiple packages
- `getPricingDisplayText($package)` - Get display text based on status

**Pricing Logic:**

```php
// Residential: 20% of price range
// Business: 50% of price range  
// Enterprise: 80% of price range

// Custom enterprise: +50% premium
// Site survey required: +$100 installation
// Bandwidth-based: +$50 per 100Mbps
```

### 4. Updated Controllers

**ProductController.php:**
- All endpoints now use `PricingSimulationService`
- Returns `simulation_enabled` flag in response
- Packages include `is_simulated_pricing` flag when simulated

**Updated Endpoints:**
- `GET /api/products` - All products with simulated pricing
- `GET /api/products/{id}` - Single product with simulated pricing
- `GET /api/products/available` - Available packages with simulated pricing
- `GET /api/packages` - Public packages with simulated pricing

### 5. Frontend Integration

**Products Page Updates:**
- Shows "ⓘ Estimated pricing" badge on simulated packages
- Maintains all existing functionality
- No breaking changes to UI

---

## Package Behavior

### Starlink (Satellite)
```json
{
  "code": "STARLINK-1TB",
  "has_fixed_pricing": true,
  "monthly_price": 155.00,
  "is_simulated_pricing": false  // Never simulated
}
```

### Magellan Metro-VPN (Feasibility-Based)
```json
{
  "code": "MAGELLAN-MVPN",
  "has_fixed_pricing": false,
  "base_price": 500.00,
  "monthly_price": 500.00,  // From base_price
  "installation_fee": 1200.00,  // Calculated
  "is_simulated_pricing": true,  // When SIMULATE_PACKAGE_PRICING=true
  "pricing_note": "Estimated pricing for demonstration..."
}
```

### DIA (Custom Enterprise)
```json
{
  "code": "DIA",
  "has_fixed_pricing": false,
  "pricing_model": "bandwidth_based",
  "monthly_price": 250.00,  // Simulated based on characteristics
  "installation_fee": 750.00,  // Simulated
  "is_simulated_pricing": true,
  "pricing_note": "Estimated pricing for demonstration..."
}
```

---

## Usage Scenarios

### Scenario 1: Development/Testing (SIMULATE_PACKAGE_PRICING=true)

```
User browses products
  ↓
All packages show pricing
  ↓
Packages without fixed pricing show:
  - Estimated monthly price
  - Estimated installation fee
  - "ⓘ Estimated pricing" badge
  ↓
User can add to cart and test checkout flow
  ↓
Quotation still created for non-fixed packages
```

### Scenario 2: Production (SIMULATE_PACKAGE_PRICING=false)

```
User browses products
  ↓
Fixed-price packages (Starlink) show pricing
  ↓
Custom packages show:
  - "Request Quote" button only
  - No pricing displayed
  ↓
User requests quotation
  ↓
Admin provides actual pricing in Odoo
  ↓
User receives quotation with real prices
```

---

## API Response Examples

### With Simulation Enabled

```json
{
  "success": true,
  "simulation_enabled": true,
  "data": [
    {
      "id": 1,
      "name": "Starlink Package - 1 TB Priority Access",
      "code": "STARLINK-1TB",
      "monthly_price": 155.00,
      "installation_fee": 0.00,
      "has_fixed_pricing": true,
      "is_simulated_pricing": false
    },
    {
      "id": 2,
      "name": "Magellan Metro-VPN",
      "code": "MAGELLAN-MVPN",
      "monthly_price": 500.00,
      "installation_fee": 1200.00,
      "has_fixed_pricing": false,
      "is_simulated_pricing": true,
      "pricing_note": "Estimated pricing for demonstration. Actual pricing will be provided in quotation."
    }
  ]
}
```

### With Simulation Disabled

```json
{
  "success": true,
  "simulation_enabled": false,
  "data": [
    {
      "id": 1,
      "name": "Starlink Package - 1 TB Priority Access",
      "code": "STARLINK-1TB",
      "monthly_price": 155.00,
      "installation_fee": 0.00,
      "has_fixed_pricing": true,
      "is_simulated_pricing": false
    },
    {
      "id": 2,
      "name": "Magellan Metro-VPN",
      "code": "MAGELLAN-MVPN",
      "monthly_price": null,
      "installation_fee": null,
      "has_fixed_pricing": false,
      "is_simulated_pricing": false
    }
  ]
}
```

---

## Configuration Guide

### For Development/Testing:
```env
SIMULATE_PACKAGE_PRICING=true
SIMULATE_MONTHLY_PRICE_MIN=50
SIMULATE_MONTHLY_PRICE_MAX=500
SIMULATE_INSTALLATION_FEE_MIN=100
SIMULATE_INSTALLATION_FEE_MAX=1000
```

### For Production:
```env
SIMULATE_PACKAGE_PRICING=false
```

### For Custom Ranges:
```env
SIMULATE_PACKAGE_PRICING=true
SIMULATE_MONTHLY_PRICE_MIN=100    # Higher minimum
SIMULATE_MONTHLY_PRICE_MAX=2000   # Higher maximum for enterprise
SIMULATE_INSTALLATION_FEE_MIN=500
SIMULATE_INSTALLATION_FEE_MAX=5000
```

---

## Testing

### Test Simulation Enabled:

```bash
# Set in .env
SIMULATE_PACKAGE_PRICING=true

# Clear config cache
php artisan config:clear

# Test API
curl http://localhost:8000/api/products | jq '.simulation_enabled'
# Should return: true

# Check package pricing
curl http://localhost:8000/api/products | jq '.data[] | {name, monthly_price, is_simulated_pricing}'
```

### Test Simulation Disabled:

```bash
# Set in .env
SIMULATE_PACKAGE_PRICING=false

# Clear config cache
php artisan config:clear

# Test API
curl http://localhost:8000/api/products | jq '.simulation_enabled'
# Should return: false

# Check package pricing
curl http://localhost:8000/api/products | jq '.data[] | select(.has_fixed_pricing == false) | {name, monthly_price}'
# Should show null for non-fixed packages
```

---

## Files Modified

### Backend:
1. `.env` - Added simulation configuration
2. `.env.example` - Added simulation configuration template
3. `config/services.php` - Added pricing_simulation config
4. `app/Services/PricingSimulationService.php` - NEW: Core simulation logic
5. `app/Services/PricingService.php` - Updated to use simulation service
6. `app/Http/Controllers/API/ProductController.php` - Apply simulation to all endpoints

### Frontend:
1. `afinet-portal/src/app/(portal)/products/page.js` - Show simulation badge

---

## Benefits

✅ **Flexible Testing** - Enable/disable with single env variable  
✅ **Realistic Pricing** - Intelligent calculation based on package characteristics  
✅ **No Code Changes** - Switch between modes without code modifications  
✅ **Clear Indicators** - Users see "Estimated pricing" badge  
✅ **Production Ready** - Disable simulation for real quotations  
✅ **Maintains Workflow** - Quotation process still works correctly  

---

## Future Enhancements

1. **Admin Override** - Allow admins to set specific simulated prices per package
2. **Price History** - Track simulated vs actual quotation prices
3. **A/B Testing** - Test different pricing strategies
4. **Regional Pricing** - Different simulation ranges by region
5. **Seasonal Adjustments** - Adjust simulation based on demand

---

## Important Notes

⚠️ **Production Deployment:**
- Set `SIMULATE_PACKAGE_PRICING=false` in production
- Simulated pricing is for testing/demo only
- Real pricing comes from Odoo quotations

⚠️ **Starlink Exception:**
- Starlink always shows real pricing ($155)
- Never simulated because `has_fixed_pricing = true`

⚠️ **Quotation Workflow:**
- Simulation doesn't bypass quotation process
- Custom packages still require quotation approval
- Admins provide final pricing in Odoo

---

## Conclusion

The pricing simulation system provides a flexible way to test and demonstrate the portal with realistic pricing while maintaining the proper quotation workflow for production use. Simply toggle the environment variable to switch between modes.

