mimisk/laravel-quotes

Simple quote utilities for Laravel applications.

Maintainers

Package info

github.com/MimisK13/laravel-quotes

pkg:composer/mimisk/laravel-quotes

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.0.4 2026-04-26 06:31 UTC

README

Tests Latest Version on Packagist Total Downloads codecov

A lightweight Laravel package that provides quote helpers with config-driven defaults.

Installation

Via Composer

composer require mimisk/laravel-quotes

Usage

Publish config (optional):

php artisan vendor:publish --tag=quotes-config

Create a quote (owner can be any morphable Eloquent model, e.g. Customer):

use Mimisk\LaravelQuotes\Actions\CreateQuoteAction;
use Mimisk\LaravelQuotes\DTOs\QuoteData;

$quote = app(CreateQuoteAction::class)->handle(QuoteData::fromArray([
    'owner' => $customer,
    'title' => 'Customer Products Quote',
    'currency' => 'EUR',
    'discount_type' => 'fixed', // fixed | percentage
    'discount_value' => 50,
    'items' => [
        [
            'name' => 'Product A',
            'quantity' => 2,
            'unit_price' => 120,
            'tax_rate' => 24,
        ],
        [
            'name' => 'Product B',
            'quantity' => 1,
            'unit_price' => 85,
            'tax_rate' => 24,
        ],
    ],
]));

Update a draft quote:

use Mimisk\LaravelQuotes\Actions\UpdateQuoteAction;
use Mimisk\LaravelQuotes\DTOs\QuoteData;

app(UpdateQuoteAction::class)->handle(
    $quote,
    QuoteData::fromArray([
        'owner' => $customer,
        'title' => 'Updated Customer Quote',
        'items' => [
            [
                'name' => 'Product A (Updated)',
                'quantity' => 3,
                'unit_price' => 110,
                'tax_rate' => 24,
            ],
        ],
    ])
);

Status transitions:

use Mimisk\LaravelQuotes\Actions\AcceptQuoteAction;
use Mimisk\LaravelQuotes\Actions\ExpireQuoteAction;
use Mimisk\LaravelQuotes\Actions\RejectQuoteAction;
use Mimisk\LaravelQuotes\Actions\SendQuoteAction;

app(SendQuoteAction::class)->handle($quote);    // draft -> sent
app(AcceptQuoteAction::class)->handle($quote);  // sent -> accepted
app(RejectQuoteAction::class)->handle($quote);  // sent -> rejected
app(ExpireQuoteAction::class)->handle($quote);  // sent -> expired

Delete a quote:

use Mimisk\LaravelQuotes\Actions\DeleteQuoteAction;

app(DeleteQuoteAction::class)->handle($quote); // only draft or rejected

Error Handling

Actions may throw domain exceptions when an invalid operation is attempted.

For example, trying to accept a quote that is not in the sent state will throw an InvalidQuoteTransition exception.

You can handle these exceptions using a simple try/catch:

use Mimisk\LaravelQuotes\Exceptions\InvalidQuoteTransition;

try {
    app(AcceptQuoteAction::class)->handle($quote);
} catch (InvalidQuoteTransition $exception) {
    return back()->with('error', $exception->getMessage());
}

Alternatively, you may handle these exceptions globally using Laravel's exception handler:

// bootstrap/app.php

use Mimisk\LaravelQuotes\Exceptions\InvalidQuoteTransition;

->withExceptions(function ($exceptions) {
    $exceptions->render(function (InvalidQuoteTransition $exception) {
        return back()->with('error', $exception->getMessage());
    });
})

Quote Expiration Automation

The package provides an Artisan command to automatically expire quotes based on the valid_until field.

Run the command manually:

php artisan quotes:expire

The command will find all sent quotes where valid_until has passed and mark them as expired.

You may schedule it in your application using Laravel's scheduler:

use Illuminate\Support\Facades\Schedule;

Schedule::command('quotes:expire')->daily();

You can adjust the frequency as needed:

Schedule::command('quotes:expire')->hourly();

Events

The package dispatches the following events:

  • QuoteCreated
  • QuoteUpdated
  • QuoteSent
  • QuoteAccepted
  • QuoteRejected
  • QuoteExpired

Change log

Please see the CHANGELOG for more information on what has changed recently.

Testing

composer test

Security

If you discover any security related issues, please email mimisk88@gmail.com instead of using the issue tracker.

Credits

License

MIT. Please see the LICENSE file for more information.