Skip to content

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

FieldTypeDescription
idintegerAuto-generated
product_idintegerParent product
min_quantitydecimal(15,3)Minimum quantity to activate this tier
max_quantitydecimal(15,3)?Maximum quantity (null = unlimited)
price_typeenumfixed_price, percentage_discount
valuedecimal(15,3)The fixed price or discount percentage
is_activebooleanWhether this tier is active

Price Types

TypeCalculationExample
fixed_priceUse value as the unit pricevalue=80 means unit price becomes 80
percentage_discountsale_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

MethodEndpointDescription
GET/api/core/products/{productId}/pricing-tiersList all tiers (sorted by min_quantity)
POST/api/core/products/{productId}/pricing-tiersCreate 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=NCheck 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:

json
{
  "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:

json
{
  "data": {
    "tier_applied": false,
    "original_price": "100.000",
    "suggested_price": "100.000",
    "tier": null
  }
}

Examples

Create a Percentage Discount Tier

bash
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
  }'
dart
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)

bash
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
  }'
dart
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

bash
curl "$BASE_URL/api/core/products/1/check-tier-price?quantity=25" \
  -H "Authorization: Bearer $TOKEN"
dart
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:

  1. Query all active tiers for the product
  2. Filter tiers where min_quantity <= quantity AND (max_quantity >= quantity OR max_quantity is null)
  3. Select the tier with the highest min_quantity (most specific match)
  4. 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:

PermissionDescription
core.products.viewList tiers and check tier price
core.products.createCreate pricing tiers
core.products.updateUpdate pricing tiers
core.products.deleteDelete pricing tiers

Moon ERP API Documentation