Product Tiered Pricing (تسعير الكميات)
Tiered pricing allows you to define quantity-based pricing rules per product. When a customer orders above a threshold quantity, they automatically get a discounted price.
Pricing Tier Attributes
| Field | Type | Description |
|---|---|---|
id | integer | Auto-generated |
product_id | integer | Parent product |
min_quantity | decimal(15,3) | Minimum quantity to activate this tier |
max_quantity | decimal(15,3)? | Maximum quantity (null = unlimited) |
price_type | enum | fixed_price, percentage_discount |
value | decimal(15,3) | The fixed price or discount percentage |
is_active | boolean | Whether this tier is active |
Price Types
| Type | Calculation | Example |
|---|---|---|
fixed_price | Use value as the unit price | value=80 means unit price becomes 80 |
percentage_discount | sale_price * (1 - value/100) | value=10, sale_price=100 means unit price becomes 90 |
Overlap Validation
The system ensures no two tiers overlap in their quantity ranges for the same product. Creating or updating a tier that would overlap with an existing range returns a 422 error.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/core/products/{productId}/pricing-tiers | List all tiers (sorted by min_quantity) |
POST | /api/core/products/{productId}/pricing-tiers | Create tier |
PUT | /api/core/products/{productId}/pricing-tiers/{tierId} | Update tier |
DELETE | /api/core/products/{productId}/pricing-tiers/{tierId} | Soft-delete tier |
GET | /api/core/products/{productId}/check-tier-price?quantity=N | Check applicable tier |
Check Tier Price Response
The check-tier-price endpoint returns the applicable tier and suggested price for a given quantity.
When a tier applies:
{
"data": {
"tier_applied": true,
"original_price": "100.000",
"suggested_price": "90.000",
"discount_percentage": "10.000",
"tier": { "id": 1, "min_quantity": "10.000", "..." : "..." }
}
}When no tier applies:
{
"data": {
"tier_applied": false,
"original_price": "100.000",
"suggested_price": "100.000",
"tier": null
}
}Examples
Create a Percentage Discount Tier
curl -X POST "$BASE_URL/api/core/products/1/pricing-tiers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"min_quantity": 10,
"max_quantity": 50,
"price_type": "percentage_discount",
"value": 10.000,
"is_active": true
}'final response = await dio.post(
'/api/core/products/1/pricing-tiers',
data: {
'min_quantity': 10,
'max_quantity': 50,
'price_type': 'percentage_discount',
'value': 10.000,
'is_active': true,
},
);Create a Fixed Price Tier (Unlimited Max)
curl -X POST "$BASE_URL/api/core/products/1/pricing-tiers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"min_quantity": 100,
"max_quantity": null,
"price_type": "fixed_price",
"value": 75.000
}'final response = await dio.post(
'/api/core/products/1/pricing-tiers',
data: {
'min_quantity': 100,
'max_quantity': null,
'price_type': 'fixed_price',
'value': 75.000,
},
);Check Tier Price for a Quantity
curl "$BASE_URL/api/core/products/1/check-tier-price?quantity=25" \
-H "Authorization: Bearer $TOKEN"final response = await dio.get(
'/api/core/products/1/check-tier-price',
queryParameters: {'quantity': 25},
);
// response.data['data']['suggested_price'] -> "90.000"Tier Matching Logic
When checking a tier price for a given quantity:
- Query all active tiers for the product
- Filter tiers where
min_quantity <= quantityAND (max_quantity >= quantityORmax_quantityis null) - Select the tier with the highest
min_quantity(most specific match) - Calculate the suggested price based on the tier's
price_type
Integration with Sales Documents
Tiers are included in the product show response (GET /api/core/products/{id}) under the pricing_tiers key. The frontend uses the check-tier-price endpoint when adding line items to quotations, orders, or invoices to suggest the appropriate unit price.
Permissions
Tiered pricing uses the existing product permissions:
| Permission | Description |
|---|---|
core.products.view | List tiers and check tier price |
core.products.create | Create pricing tiers |
core.products.update | Update pricing tiers |
core.products.delete | Delete pricing tiers |