Search by

itmosoft / laravel-pricing

adeelrao007

A reusable Laravel pricing package with polymorphic prices, currency support, scheduled pricing, quantity breaks, and contextual price resolution.

Package info

github.com/ITMOSOFT/laravel-pricing

pkg:composer/itmosoft/laravel-pricing

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-11-04 11:51 UTC

This package is auto-updated.

Last update: 2026-11-04 11:53:47 UTC


README

A reusable Laravel pricing package for polymorphic model pricing, multiple currencies, scheduled prices, quantity breaks, and context-specific price resolution.

Requirements

  • PHP 8.3+
  • Laravel 12 or 13

Installation

composer require itmosoft/laravel-pricing
php artisan vendor:publish --tag=pricing-config
php artisan migrate

Attach the price relationship

Add a morph-many relationship to any Eloquent model that needs pricing:

use Illuminate\Database\Eloquent\Relations\MorphMany;
use ItmoSoft\Pricing\Models\Price;

public function prices(): MorphMany
{
    return $this->morphMany(Price::class, 'priceable');
}

Create prices

$product->prices()->create([
    'currency' => 'USD',
    'amount' => 99.00,
    'compare_at_amount' => 119.00,
    'min_quantity' => 1,
    'is_active' => true,
]);

// Quantity break
$product->prices()->create([
    'currency' => 'USD',
    'amount' => 85.00,
    'min_quantity' => 10,
    'is_active' => true,
]);

// Context-specific price
$product->prices()->create([
    'currency' => 'USD',
    'amount' => 75.00,
    'context' => ['customer_group' => 'wholesale'],
    'is_active' => true,
]);

Resolve a price

use ItmoSoft\Pricing\Services\PriceResolver;

$price = app(PriceResolver::class)->resolve(
    priceable: $product,
    currency: 'USD',
    quantity: 12,
    context: ['customer_group' => 'wholesale'],
);

if ($price !== null) {
    $price->amount;
    $price->compare_at_amount;
}

Resolution rules:

  1. Match the model, currency, active state, quantity threshold, and current schedule.
  2. A price's context must be a subset of the supplied context with exact key/value matches.
  3. The most context-specific matching price wins.
  4. Ties are resolved by higher priority, then newest record.
  5. Returns null when no price applies.

The caller is responsible for supplying trusted context values and handling a missing price.

Scheduled pricing

starts_at and ends_at are inclusive boundaries. Null means no boundary.

$product->prices()->create([
    'currency' => 'USD',
    'amount' => 79.00,
    'starts_at' => now()->startOfDay(),
    'ends_at' => now()->addDays(7)->endOfDay(),
    'is_active' => true,
]);

Configuration

Publish config/pricing.php:

php artisan vendor:publish --tag=pricing-config
  • table_prefix: default pricing_; configure before running migrations.
  • default_currency: default USD.
  • models.price: price model class mapping.

The default table is pricing_prices.

Design boundaries

This package provides price storage and deterministic price resolution. It does not implement tax calculation, currency conversion, coupon codes, promotion campaigns, cart totals, checkout, payment processing, or automatic scheduled activation jobs. Store monetary amounts in the chosen currency; this package does not perform FX conversion.

Testing

composer install
composer validate --no-check-publish
composer test

GitHub Actions tests Laravel 12 and 13 separately using the matching Orchestra Testbench major version.

License

MIT. See LICENSE.