# NexusMart Product Discount System

## Overview

The discount system allows for flexible product and order-level discounts with multiple discount types, date ranges, usage limits, and applicability rules.

## Features

### 1. **Discount Types**
- **Percentage Discounts**: 0-100% off any product
- **Fixed Amount Discounts**: Direct currency amount (e.g., $5,000 off)

### 2. **Applicability**
- Apply to all products
- Apply to specific products
- Apply to specific categories
- Mix and match categories and products

### 3. **Availability Control**
- Date range restrictions (start_date to end_date)
- Active/inactive toggle
- Automatic expiration after end date

### 4. **Usage Management**
- Global usage limit (e.g., only 100 uses total)
- Per-user usage limit (e.g., each customer can use max 3 times)
- Automatic usage tracking
- Minimum purchase requirement (e.g., applies only to orders over $50,000)

### 5. **Promotional Codes**
- Optional discount codes (e.g., "SAVE20", "WELCOME10")
- Code-based or automatic discounts
- Case-insensitive code matching

## Models

### Discount Model

```python
class Discount(models.Model):
    # Basic Info
    name                  # e.g., "Summer Sale 2026"
    description           # Detailed description
    code                  # Optional promo code
    
    # Discount Details
    discount_type         # 'percentage' or 'fixed'
    discount_value        # The discount amount
    min_purchase          # Minimum purchase to qualify
    
    # Applicability
    products              # ManyToMany - specific products (optional)
    categories            # ManyToMany - specific categories (optional)
    
    # Availability
    is_active             # On/off toggle
    start_date            # When discount becomes active
    end_date              # When discount expires
    
    # Usage Limits
    usage_limit           # Total uses allowed (optional)
    usage_count           # Current usage count (auto-updated)
    usage_limit_per_user  # Max uses per customer (optional)
    
    # Tracking
    created_by            # Admin who created it
    created_at
    updated_at
```

## Admin Interface

Access discounts at: `Django Admin > Shop > Discounts`

### Creating a Discount

1. **Name & Description**: Give the discount a meaningful name and description
2. **Discount Type**: Choose percentage or fixed amount
3. **Discount Value**: 
   - For percentage: Enter 0-100
   - For fixed amount: Enter the amount in currency
4. **Applicability**:
   - Leave both empty for store-wide discount
   - Or select specific products/categories
5. **Date Range**: Set when discount is active
6. **Usage Limits**: Set optional limits
7. **Minimum Purchase**: Set minimum cart total to qualify

### Example Discounts

```
1. "Black Friday Sale"
   - 30% off all products
   - Code: BLACKFRIDAY30
   - Active: Nov 1-30, 2026
   - No usage limit

2. "First Purchase"
   - $2,000 off
   - Applies to new customers
   - Min purchase: $10,000
   - Limit: 1 use per user

3. "Electronics Sale"
   - 15% off Electronics category
   - Active: Apr 1-30, 2026
   - Auto-applied (no code needed)

4. "Loyalty Reward"
   - $5,000 off
   - Code: LOYAL2026
   - Limit: 10 total uses
   - Min purchase: $50,000
```

## Backend Usage

### In Views

```python
from shop.discount_views import calculate_cart_totals, get_applied_discount
from shop.models import Discount

def checkout(request):
    cart = Cart.objects.get(user=request.user)
    
    # Get applied discount from session
    discount = get_applied_discount(request)
    
    # Calculate totals
    totals = calculate_cart_totals(cart, discount)
    
    context = {
        'subtotal': totals['subtotal'],
        'discount_amount': totals['discount_amount'],
        'total': totals['total'],
        'discount': discount,
    }
    
    return render(request, 'checkout.html', context)
```

### In Templates

```html
<!-- Display discount on product -->
{% load discount_tags %}
{% with discount_info=product|get_discount_info %}
    {% if discount_info.has_discount %}
        <div class="discount-badge">
            <span class="save-amount">Save {{ discount_info.discount_percent }}%</span>
            <p class="original-price">${{ discount_info.original_price }}</p>
            <p class="discounted-price">${{ discount_info.discounted_price }}</p>
            <small>{{ discount_info.discount_name }}</small>
        </div>
    {% endif %}
{% endwith %}

<!-- Discount code form in checkout -->
<form method="post" action="{% url 'shop:apply_discount_code' %}">
    {% csrf_token %}
    <div class="input-group">
        <input type="text" name="code" placeholder="Enter discount code" class="form-control">
        <button type="submit" class="btn btn-primary">Apply</button>
    </div>
</form>

<!-- Display applied discount -->
{% if discount %}
    <div class="alert alert-success">
        <strong>{{ discount.name }}</strong> applied!
        You save ${{ discount_amount }}
    </div>
{% endif %}
```

## API Endpoints

### Apply Discount Code
```
POST /discount/apply/

Parameters:
- code: str (discount code)

Response:
{
    "success": true/false,
    "message": "...",
    "discount": {
        "name": "...",
        "value": "20",
        "type": "Percentage (%)"
    },
    "totals": {
        "subtotal": "100000.00",
        "discount_amount": "20000.00",
        "total": "80000.00"
    }
}
```

### Remove Discount
```
POST /discount/remove/

Response:
{
    "success": true/false,
    "message": "..."
}
```

## Key Methods

### Discount Model Methods

```python
discount = Discount.objects.get(id=1)

# Check if discount is currently valid
discount.is_valid()  # Returns bool

# Check if user can use this discount
discount.can_user_use(user)  # Returns bool

# Check if discount applies to product
discount.is_applicable_to_product(product)  # Returns bool

# Calculate discount amount
discount.calculate_discount_amount(1000)  # Returns Decimal

# Calculate final price
discount.calculate_discounted_price(1000)  # Returns Decimal

# Record usage
discount.apply()  # Increments usage_count
```

### Product Methods

```python
product = Product.objects.get(id=1)

# Get best active discount for product
product.get_active_discount()  # Returns Discount or None
```

### Utility Functions

```python
from shop.discount_views import (
    calculate_cart_totals,
    get_applied_discount,
    get_product_discount_info,
    apply_discount_code,
    remove_discount_code
)

# Get discount info for display
info = get_product_discount_info(product)
# Returns dict with discount details

# Get currently applied discount
discount = get_applied_discount(request)

# Calculate totals with discount
totals = calculate_cart_totals(cart, discount)
# Returns dict with subtotal, discount_amount, total, etc.
```

## Order Integration

Orders track:
- `discount` - Which discount was applied
- `subtotal` - Pre-discount total
- `discount_amount` - Amount saved
- `total` - Final amount to pay

```python
order.subtotal      # $100,000
order.discount      # <Discount: Summer Sale - 20%>
order.discount_amount  # $20,000
order.total         # $80,000
```

## Best Practices

1. **Always validate** discount before applying:
   ```python
   if discount.is_valid() and discount.can_user_use(user):
       # Apply discount
   ```

2. **Display savings** clearly to customers:
   ```
   "Save $20,000 with this discount!"
   ```

3. **Set realistic limits** to prevent abuse:
   - Set usage limits for popular discounts
   - Set per-user limits for loyalty discounts
   - Require minimum purchases for aggressive discounts

4. **Test edge cases**:
   - Multiple discounts (currently best is chosen)
   - Expired discounts
   - Used up discounts
   - Out-of-scope products

5. **Monitor usage**:
   - Check `usage_count` vs `usage_limit` in admin
   - Archive expired discounts
   - Review popular discounts for expansion

## Troubleshooting

### Discount Not Applying
1. Check if discount is `is_active=True`
2. Check current date is within `start_date` and `end_date`
3. Check `usage_limit` not exceeded
4. Check user hasn't exceeded `usage_limit_per_user`
5. Check cart total >= `min_purchase`

### Code Not Found
- Codes are case-insensitive
- Check code exists in database
- Check code is set on discount (some auto-apply)

### Wrong Discount Selected
- System chooses discount with highest savings
- If product has multiple discounts, best one wins
- Category discounts also considered

## Migration

After adding discount functionality, run:
```bash
python manage.py migrate shop
```

This creates the Discount table and adds discount fields to Order.

## Future Enhancements

- [ ] Tiered discounts (buy more, save more)
- [ ] Combination discount rules
- [ ] Referral discounts
- [ ] Gift card integration
- [ ] Bulk order discounts
- [ ] Time-based dynamic pricing
- [ ] AI-based personalized discounts
- [ ] Discount analytics dashboard
