# Product API Testing Guide - Postman Collection

This guide covers all possible product creation/update scenarios based on channel and variant configurations.

## Base Configuration

**Base URL:** `{{BASE_URL}}/api/products` or `{{BASE_URL}}/products` (tenant routes)

**Headers:**

```
Content-Type: application/json
Accept: application/json
Authorization: Bearer {{TOKEN}}
```

---

## Scenario 1: Simple Product - No Channel Pricing - Same Price All Branches

**Configuration:**

- `channel`: `false` (or omitted)
- `has_variants`: `false`
- `same_price_all_branches`: `true`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "Simple Product - Universal Price",
    "slug": "simple-product-universal-price",
    "sku": "SP-001",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_codes": true,
    "track_inventory": true,
    "has_variants": false,
    "same_price_all_branches": true,
    "channel": false,

    "product_code": "PC-001",
    "barcode": "123456789",
    "description": "Simple product with universal pricing",
    "short_description": "Simple product",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 100,
            "cost_price": 50,
            "reorder_level": 10
        }
    ],

    "universal": {
        "simple": {
            "retail": 100,
            "compareAt": 120,
            "wholesale": 80,
            "cost": 50,
            "special_price": null,
            "is_bundle": false,
            "bundle_price": null,
            "min_qty_wholesale": 10
        }
    },

    "tags": ["electronics", "featured"],
    "media_id": 1,
    "media_ids": [1, 2, 3]
}
```

**Expected Result:**

- Creates product in `products` table
- Creates single price record in `product_prices` table with `branch_id = null`
- No records in `product_channel_prices`

---

## Scenario 2: Simple Product - No Channel Pricing - Different Price Per Branch

**Configuration:**

- `channel`: `false` (or omitted)
- `has_variants`: `false`
- `same_price_all_branches`: `false`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "Simple Product - Branch Pricing",
    "slug": "simple-product-branch-pricing",
    "sku": "SP-002",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": false,
    "same_price_all_branches": false,
    "channel": false,

    "product_code": "PC-002",
    "barcode": "123456790",
    "description": "Simple product with branch-specific pricing",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 50,
            "cost_price": 45
        },
        {
            "branch_id": 2,
            "stock_qty": 30,
            "cost_price": 48
        }
    ],

    "branch": {
        "1": {
            "simple": {
                "retail": 95,
                "wholesale": 75,
                "cost": 45,
                "min_qty_wholesale": 10
            }
        },
        "2": {
            "simple": {
                "retail": 105,
                "wholesale": 85,
                "cost": 48,
                "min_qty_wholesale": 10
            }
        }
    },

    "tags": ["branch-specific"]
}
```

**Expected Result:**

- Creates product in `products` table
- Creates 2 price records in `product_prices` table (one per branch)
- No records in `product_channel_prices`

---

## Scenario 3: Simple Product - WITH Channel Pricing - Same Price All Channels

**Configuration:**

- `channel`: `true`
- `has_variants`: `false`
- `same_price_all_branches`: `true`
- `same_price_for_all_channels`: `true` (implied when only default channel used)

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "Simple Product - Channel Universal Price",
    "slug": "simple-product-channel-universal-price",
    "sku": "SP-003",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": false,
    "same_price_all_branches": true,
    "channel": true,
    "sales_channels": "pos",

    "product_code": "PC-003",
    "description": "Simple product with channel pricing - universal",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 100,
            "cost_price": 50
        }
    ],

    "universal": {
        "simple": {
            "retail": 100,
            "wholesale": 80,
            "cost": 50,
            "min_qty_wholesale": 5
        }
    }
}
```

**Expected Result:**

- Creates product in `products` table
- Creates 1 price record in `product_channel_prices` with `channel = 'pos'`, `is_branch_price = 0`
- No records in `product_prices`

---

## Scenario 4: Simple Product - WITH Channel Pricing - Different Price Per Channel

**Configuration:**

- `channel`: `true`
- `has_variants`: `false`
- `same_price_all_branches`: `true`
- `same_price_for_all_channels`: `false`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "Simple Product - Multi-Channel Pricing",
    "slug": "simple-product-multi-channel-pricing",
    "sku": "SP-004",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": false,
    "same_price_all_branches": true,
    "same_price_for_all_channels": false,
    "channel": true,
    "sales_channels": "pos,offline,online",

    "product_code": "PC-004",
    "description": "Simple product with different pricing per channel",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 100,
            "cost_price": 50
        }
    ],

    "universal": {
        "simple": {
            "retail": 100,
            "wholesale": 80,
            "cost": 50
        }
    }
}
```

**Expected Result:**

- Creates product in `products` table
- Creates 3 price records in `product_channel_prices` (one for each channel: pos, offline, online)
- All with `is_branch_price = 0`
- No records in `product_prices`

---

## Scenario 5: Variant Product - No Channel Pricing - Same Price All Branches

**Configuration:**

- `channel`: `false` (or omitted)
- `has_variants`: `true`
- `same_price_all_branches`: `true`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "T-Shirt with Variants - Universal Price",
    "slug": "t-shirt-with-variants-universal-price",
    "sku": "VP-001",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": true,
    "same_price_all_branches": true,
    "channel": false,

    "product_code": "PC-005",
    "description": "T-shirt with size and color variants",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 200,
            "cost_price": 25
        }
    ],

    "product_options": [
        {
            "id": "temp-1",
            "name": "Size",
            "values": ["Small", "Medium", "Large"]
        },
        {
            "id": "temp-2",
            "name": "Color",
            "values": ["Red", "Blue", "Black"]
        }
    ],

    "product_variants": [
        {
            "id": "var-1",
            "title": "Small / Red",
            "sku": "VP-001-SR"
        },
        {
            "id": "var-2",
            "title": "Small / Blue",
            "sku": "VP-001-SB"
        },
        {
            "id": "var-3",
            "title": "Medium / Red",
            "sku": "VP-001-MR"
        },
        {
            "id": "var-4",
            "title": "Large / Black",
            "sku": "VP-001-LB"
        }
    ],

    "universal": {
        "variants": {
            "var-1": {
                "retail": 50,
                "wholesale": 40,
                "cost": 25,
                "min_qty_wholesale": 10
            },
            "var-2": {
                "retail": 50,
                "wholesale": 40,
                "cost": 25,
                "min_qty_wholesale": 10
            },
            "var-3": {
                "retail": 55,
                "wholesale": 45,
                "cost": 27,
                "min_qty_wholesale": 10
            },
            "var-4": {
                "retail": 60,
                "wholesale": 50,
                "cost": 30,
                "min_qty_wholesale": 10
            }
        }
    }
}
```

**Expected Result:**

- Creates product in `products` table
- Creates 2 product options in `product_options`
- Creates 5 option values (3 for Size, 2 used for Color)
- Creates 4 variants in `product_variants`
- Creates 4 price records in `product_prices` (one per variant, `branch_id = null`)
- No records in `product_channel_prices`

---

## Scenario 6: Variant Product - No Channel Pricing - Different Price Per Branch

**Configuration:**

- `channel`: `false` (or omitted)
- `has_variants`: `true`
- `same_price_all_branches`: `false`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "T-Shirt with Variants - Branch Pricing",
    "slug": "t-shirt-with-variants-branch-pricing",
    "sku": "VP-002",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": true,
    "same_price_all_branches": false,
    "channel": false,

    "product_code": "PC-006",
    "description": "T-shirt with variants and branch-specific pricing",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 100,
            "cost_price": 25
        },
        {
            "branch_id": 2,
            "stock_qty": 80,
            "cost_price": 27
        }
    ],

    "product_options": [
        {
            "id": "temp-1",
            "name": "Size",
            "values": ["Small", "Medium"]
        }
    ],

    "product_variants": [
        {
            "id": "var-1",
            "title": "Small",
            "sku": "VP-002-S"
        },
        {
            "id": "var-2",
            "title": "Medium",
            "sku": "VP-002-M"
        }
    ],

    "branch": {
        "1": {
            "variants": {
                "var-1": {
                    "retail": 50,
                    "wholesale": 40,
                    "cost": 25
                },
                "var-2": {
                    "retail": 55,
                    "wholesale": 45,
                    "cost": 27
                }
            }
        },
        "2": {
            "variants": {
                "var-1": {
                    "retail": 52,
                    "wholesale": 42,
                    "cost": 25
                },
                "var-2": {
                    "retail": 57,
                    "wholesale": 47,
                    "cost": 27
                }
            }
        }
    }
}
```

**Expected Result:**

- Creates product with variants
- Creates 4 price records in `product_prices` (2 variants × 2 branches)
- Each price has specific `branch_id` and `product_variant_id`
- No records in `product_channel_prices`

---

## Scenario 7: Variant Product - WITH Channel Pricing - Same Price All Channels

**Configuration:**

- `channel`: `true`
- `has_variants`: `true`
- `same_price_all_branches`: `true`
- Default channel: `pos`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "T-Shirt Variants - Channel Universal",
    "slug": "t-shirt-variants-channel-universal",
    "sku": "VP-003",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": true,
    "same_price_all_branches": true,
    "channel": true,
    "sales_channels": "pos",

    "product_code": "PC-007",
    "description": "Variant product with channel pricing",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 150,
            "cost_price": 30
        }
    ],

    "product_options": [
        {
            "id": "temp-1",
            "name": "Size",
            "values": ["Small", "Large"]
        }
    ],

    "product_variants": [
        {
            "id": "var-1",
            "title": "Small",
            "sku": "VP-003-S"
        },
        {
            "id": "var-2",
            "title": "Large",
            "sku": "VP-003-L"
        }
    ],

    "universal": {
        "variants": {
            "var-1": {
                "retail": 60,
                "wholesale": 50,
                "cost": 30
            },
            "var-2": {
                "retail": 70,
                "wholesale": 60,
                "cost": 35
            }
        }
    }
}
```

**Expected Result:**

- Creates product with 2 variants
- Creates 2 price records in `product_channel_prices` (one per variant)
- Each with `channel = 'pos'`, `is_branch_price = 0`
- No records in `product_prices`

---

## Scenario 8: Variant Product - WITH Channel Pricing - Different Price Per Channel

**Configuration:**

- `channel`: `true`
- `has_variants`: `true`
- `same_price_all_branches`: `true`
- `same_price_for_all_channels`: `false`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "T-Shirt Variants - Multi-Channel",
    "slug": "t-shirt-variants-multi-channel",
    "sku": "VP-004",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": true,
    "same_price_all_branches": true,
    "same_price_for_all_channels": false,
    "channel": true,
    "sales_channels": "pos,offline,online",

    "product_code": "PC-008",
    "description": "Variant product with multi-channel pricing",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 200,
            "cost_price": 30
        }
    ],

    "product_options": [
        {
            "id": "temp-1",
            "name": "Size",
            "values": ["Small", "Large"]
        }
    ],

    "product_variants": [
        {
            "id": "var-1",
            "title": "Small",
            "sku": "VP-004-S"
        },
        {
            "id": "var-2",
            "title": "Large",
            "sku": "VP-004-L"
        }
    ],

    "universal": {
        "variants": {
            "var-1": {
                "retail": 60,
                "wholesale": 50,
                "cost": 30
            },
            "var-2": {
                "retail": 70,
                "wholesale": 60,
                "cost": 35
            }
        }
    }
}
```

**Expected Result:**

- Creates product with 2 variants
- Creates 6 price records in `product_channel_prices` (2 variants × 3 channels)
- Each has specific `channel` (pos/offline/online) and `product_variant_id`
- All with `is_branch_price = 0`
- No records in `product_prices`

---

## Scenario 9: Variant Product - WITH Channel - Different Price Per Branch AND Channel

**Configuration:**

- `channel`: `true`
- `has_variants`: `true`
- `same_price_all_branches`: `false`
- `same_price_for_all_channels`: `false`

**Endpoint:** `POST /products`

**Request Body:**

```json
{
    "name": "T-Shirt - Branch & Channel Pricing",
    "slug": "t-shirt-branch-channel-pricing",
    "sku": "VP-005",
    "category_id": 1,
    "brand_id": 1,
    "unit_id": 1,
    "type": "goods",
    "status": 1,
    "has_variants": true,
    "same_price_all_branches": false,
    "same_price_for_all_channels": false,
    "channel": true,
    "sales_channels": "pos,online",

    "product_code": "PC-009",
    "description": "Complex pricing: variants + branches + channels",

    "inventory": [
        {
            "branch_id": 1,
            "stock_qty": 100,
            "cost_price": 30
        },
        {
            "branch_id": 2,
            "stock_qty": 80,
            "cost_price": 32
        }
    ],

    "product_options": [
        {
            "id": "temp-1",
            "name": "Size",
            "values": ["Small", "Large"]
        }
    ],

    "product_variants": [
        {
            "id": "var-1",
            "title": "Small",
            "sku": "VP-005-S"
        },
        {
            "id": "var-2",
            "title": "Large",
            "sku": "VP-005-L"
        }
    ],

    "branch": {
        "1": {
            "variants": {
                "var-1": {
                    "retail": 60,
                    "wholesale": 50,
                    "cost": 30
                },
                "var-2": {
                    "retail": 70,
                    "wholesale": 60,
                    "cost": 35
                }
            }
        },
        "2": {
            "variants": {
                "var-1": {
                    "retail": 65,
                    "wholesale": 55,
                    "cost": 32
                },
                "var-2": {
                    "retail": 75,
                    "wholesale": 65,
                    "cost": 37
                }
            }
        }
    }
}
```

**Expected Result:**

- Creates product with 2 variants
- Creates 8 price records in `product_channel_prices`:
    - 2 variants × 2 branches × 2 channels = 8 records
    - Each with specific `channel`, `branch_id` (via is_branch_price=1), and `product_variant_id`
- No records in `product_prices`

---

## Update Product Scenarios

For updating products, use the same JSON structures but with:

**Endpoint:** `PUT /products/{id}` or `PATCH /products/{id}`

The update logic will:

1. Delete existing prices
2. Delete existing variants (if structure changed)
3. Recreate everything based on new data

---

## Additional Test Endpoints

### Get All Products

```
GET /products?per_page=10&page=1
```

### Get Single Product

```
GET /products/{id}
```

### Update Product Status

```
PUT /products/{id}/status
Body: { "status": 1 }
```

### Delete Product

```
DELETE /products/{id}
```

### Bulk Actions

```
POST /products/bulk-action
Body: {
  "action": "status_update",
  "status": "active",
  "ids": [1, 2, 3]
}
```

### Export Products

```
POST /products/export
Body: {
  "ids": [1, 2, 3],
  "data": {
    "columns": ["name", "sku", "status"],
    "format": "csv"
  }
}
```

---

## Testing Checklist

### Simple Products (No Variants)

- [ ] Scenario 1: No channel, universal price
- [ ] Scenario 2: No channel, branch-specific price
- [ ] Scenario 3: With channel, same price all channels
- [ ] Scenario 4: With channel, different price per channel

### Variant Products

- [ ] Scenario 5: Variants, no channel, universal price
- [ ] Scenario 6: Variants, no channel, branch-specific price
- [ ] Scenario 7: Variants, with channel, same price all channels
- [ ] Scenario 8: Variants, with channel, different price per channel
- [ ] Scenario 9: Variants, with channel, branch + channel specific pricing

### Edge Cases

- [ ] Product with no pricing data
- [ ] Product with empty inventory
- [ ] Product with invalid variant options
- [ ] Update product from simple to variant
- [ ] Update product from variant to simple
- [ ] Update product channel settings

---

## Expected Database Records Summary

| Scenario | `products` | `product_prices`     | `product_channel_prices` | `product_variants` |
| -------- | ---------- | -------------------- | ------------------------ | ------------------ |
| 1        | 1          | 1 (branch=null)      | 0                        | 0                  |
| 2        | 1          | 2 (per branch)       | 0                        | 0                  |
| 3        | 1          | 0                    | 1 (pos)                  | 0                  |
| 4        | 1          | 0                    | 3 (pos, offline, online) | 0                  |
| 5        | 1          | 4 (per variant)      | 0                        | 4                  |
| 6        | 1          | 4 (2 var × 2 branch) | 0                        | 2                  |
| 7        | 1          | 0                    | 2 (per variant, pos)     | 2                  |
| 8        | 1          | 0                    | 6 (2 var × 3 channels)   | 2                  |
| 9        | 1          | 0                    | 8 (2 var × 2 br × 2 ch)  | 2                  |

---

## Postman Environment Variables

```json
{
    "BASE_URL": "http://localhost:8000",
    "TOKEN": "your-bearer-token-here"
}
```

## Notes

1. **Slug Auto-generation:** The `slug` field is optional. If not provided, it will be auto-generated from the product `name` using kebab-case formatting
2. **Channel Default:** When `channel=true` and `same_price_for_all_channels=false`, the system returns all channels: `['pos', 'offline', 'online']`
3. **Default Channel:** When `channel=true`, default channel is `'pos'`
4. **Variant ID Mapping:** Frontend temporary variant IDs (e.g., "var-1") are mapped to database IDs automatically
5. **Price Table Selection:** `channel=true` uses `product_channel_prices`, otherwise uses `product_prices`
