# Pricing System Guide

## How Pricing Works in Your POS System

### 🎯 Overview

Your system uses a **two-tier pricing system**:
1. **Base Price** → Determined from Price Lists (or `selling_price` fallback)
2. **Discount** → Applied to the base price to get the final price

---

## 📊 Price Determination Flow

```
Product Selection
    ↓
1. Get Base Price
    ├─→ Check Price List (default or customer-specific)
    │   ├─→ Look for variant-specific price (if variant selected)
    │   ├─→ Look for product-level price
    │   └─→ Check quantity tiers (min_quantity, max_quantity)
    │
    └─→ Fallback to Product.selling_price (if no price list price)
        └─→ Error if both are null/missing
    ↓
2. Base Price = Ksh 1000 (example)
    ↓
3. Apply Discount (if applicable)
    ├─→ Discount Code: "SAVE20"
    ├─→ Discount Type: Percentage (20%)
    └─→ Final Price = Ksh 1000 - (20% of 1000) = Ksh 800
    ↓
4. Calculate Line Total
    └─→ Final Price × Quantity = Ksh 800 × 2 = Ksh 1600
```

---

## 🔑 Key Components

### 1. **Price Lists** (`price_lists` table)
- **Purpose**: Store different pricing tiers (Retail, Wholesale, B2B, Customer-Specific)
- **Features**:
  - One default price list (marked as `is_default = true`)
  - Multiple active price lists can exist
  - Customer-specific price lists (linked to customers)
- **Auto-creation**: System auto-creates "Default Retail Price List" if none exists

### 2. **Product Prices** (`product_prices` table)
- **Purpose**: Store actual prices for products in price lists
- **Features**:
  - Can be set at **product level** (`variant_id = null`) or **variant level**
  - **Quantity-based pricing**: Different prices for different quantity ranges
  - **Effective dates**: Prices can have start/end dates (for seasonal pricing)
  - **Active flag**: Can deactivate prices without deleting them

### 3. **Product.selling_price** (fallback)
- **Purpose**: Simple default price when no price list price exists
- **Use Case**: Quick pricing without setting up price lists
- **Limitation**: Can't do quantity tiers, variant pricing, or seasonal offers

### 4. **Discounts** (`discounts` table)
- **Purpose**: Reduce the final price after base price is determined
- **Types**:
  - **Percentage**: 20% off
  - **Fixed Amount**: Ksh 100 off
  - **Buy-X-Get-Y**: Buy 2, Get 1 free
- **Important**: Discounts are **applied to the base price**, they don't set prices

---

## 💡 How to Set Up Prices

### Option 1: Using Price Lists (Recommended)

**Step 1: Create/Verify Price List**
1. Go to **Pricing → Price Lists**
2. Create a new price list OR use the default one
3. Mark one as default (`is_default = true`)

**Step 2: Add Product Prices**
1. Open a price list
2. Click "Add Product Price"
3. Select product, set price, quantity range, effective dates
4. Repeat for all products

**Benefits**:
- ✅ Quantity-based pricing (bulk discounts)
- ✅ Variant-specific pricing
- ✅ Seasonal offers (effective dates)
- ✅ Customer-specific price lists
- ✅ Easy to update prices across multiple products

### Option 2: Using Product.selling_price (Quick Fix)

**Step 1: Edit Product**
1. Go to **Products → [Select Product] → Edit**
2. Set the `selling_price` field
3. Save

**Benefits**:
- ✅ Quick and simple
- ✅ No price list setup needed

**Limitations**:
- ❌ No quantity tiers
- ❌ No variant-specific pricing
- ❌ No seasonal offers
- ❌ One price per product only

---

## 🎫 How Discounts Work

### Discount Application Process

```
1. Customer adds items to cart
   ├─→ Item 1: Product A, Qty 2, Base Price Ksh 1000 each
   └─→ Item 2: Product B, Qty 1, Base Price Ksh 500 each
   
2. Subtotal = (2 × 1000) + (1 × 500) = Ksh 2500

3. Customer applies discount code "SAVE20"
   ├─→ Discount Type: Percentage (20%)
   └─→ Discount Amount = 20% of 2500 = Ksh 500

4. Final Total = Ksh 2500 - Ksh 500 = Ksh 2000
```

### Discount Types

1. **Percentage Discount**
   - Example: "SAVE20" = 20% off
   - Applied to subtotal

2. **Fixed Amount Discount**
   - Example: "SAVE100" = Ksh 100 off
   - Applied as fixed reduction

3. **Buy-X-Get-Y**
   - Example: Buy 2, Get 1 Free
   - Free item has 100% discount applied

---

## 🔍 Current System Status

### What's Working ✅
- ✅ Price list system is fully functional
- ✅ Auto-creation of default price list
- ✅ Discount system is implemented
- ✅ Price lookup with fallback to `selling_price`
- ✅ Variant-specific pricing support
- ✅ Quantity-based pricing support

### What Needs Setup ⚠️
- ⚠️ **No prices in price lists**: Products don't have prices set up in price lists
- ⚠️ **No selling_price**: Products don't have `selling_price` set
- ⚠️ **Result**: POS shows "No price set" because no price source exists

---

## 🚀 Quick Start: Setting Prices for Your Products

### Method 1: Bulk Set selling_price (Fastest)

```sql
-- Set selling_price for all products (example prices)
UPDATE products SET selling_price = 1000 WHERE id = 1; -- Cotton Fabric
UPDATE products SET selling_price = 500 WHERE id = 2;  -- Zipper
-- ... repeat for all products
```

### Method 2: Use Price List UI (Best Practice)

1. Go to **Pricing → Price Lists**
2. Open your default price list (or create one)
3. Click "Add Product Price"
4. Select product and set price
5. Repeat for all products

### Method 3: Bulk Import (Future Enhancement)

We can create a script to bulk-import prices from CSV/Excel if needed.

---

## 📝 Code Flow Reference

### Price Lookup (in `server/modules/pricing/services/productPrices.js`)

```javascript
getPrice(productId, variantId, quantity, priceListId) {
  1. Get price list (use default if not provided)
  2. Query product_prices table:
     - Match: product_id, variant_id, price_list_id
     - Filter: active = true
     - Filter: min_quantity <= quantity <= max_quantity
     - Filter: effective_from <= now <= effective_to
  3. Return price or null
}
```

### Discount Application (in `server/modules/discounts/services/discountCalculation.js`)

```javascript
applyDiscount(discount, items, customerId) {
  1. Calculate subtotal from items (base prices)
  2. Apply discount rules:
     - Percentage: subtotal × (discount_rate / 100)
     - Fixed: discount_amount
     - Buy-X-Get-Y: calculate free items
  3. Return discount amount and final totals
}
```

### Sale Creation (in `server/modules/sales/services/index.js`)

```javascript
createSale(saleData) {
  For each item:
    1. Get base price (price list or selling_price)
    2. Calculate line total (price × quantity)
    3. Calculate VAT
  
  After all items:
    4. Apply discount (if provided)
    5. Calculate final totals
    6. Create sale record
}
```

---

## 🎯 Summary

**You were correct!** 

1. ✅ **Prices come from Price Lists** (with `selling_price` as fallback)
2. ✅ **Discounts are applied to prices** (they reduce the final price, don't set it)

**The issue**: Your products don't have prices set up in either:
- Price lists (`product_prices` table), OR
- `selling_price` field

**Solution**: Set prices using one of the methods above. Once prices are set, the POS will display them correctly, and discounts will work perfectly!

---

## 💬 Next Steps

Would you like me to:
1. **Create a bulk price import script** to set prices from a CSV/Excel file?
2. **Add a UI page** to bulk-set `selling_price` for multiple products?
3. **Show you how to set up prices** through the existing UI?

