bagisto/bagisto-crm
Bagisto CRM brings customer relationship management to your Bagisto store, helping teams track leads, customers, deals, and activities in one place. Manage pipelines, follow-ups, and sales interactions from the admin panel to build stronger relationships and close more sales.
This release (v2.2.7) is a feature-heavy minor bump on the 2.2 line — Quick Add quotes, a notifications subsystem, dashboard data filtering, and a modal-based mega search. Nothing here is flagged as breaking, so an in-place composer update is the intended path, but pin the version explicitly ("vendor/package": "2.2.7") until you've smoke-tested the two fixed forms.
Minimal steps:
composer require vendor/package:2.2.7 (or composer update vendor/package if already installed).php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider" --tag=config
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider" --tag=assets --force
php artisan migrate. Treat 2.2.7 as introducing at least one migration (notifications table, and possibly a filter-preferences table).php artisan config:clear && php artisan route:clear && php artisan view:clear, then php artisan optimize in deployed environments.php artisan queue:work — notifications are the kind of feature that assumes a worker is running.Where to look first:
config/<package>.php — diff the newly published file against your existing one rather than overwriting; look for notifications, search, and dashboard blocks.routes/ — the mega search modal endpoint and notification endpoints are new HTTP surface. Confirm middleware (auth, verified, throttle) matches your app's conventions.src/Notifications/ and any HasNotifications trait — this is the integration seam you'll actually touch.src/Http/Controllers/ for Quick Add and mega search — these are the two controllers you'll most likely override or wrap.First use case: enable the notifications channel for one entity (e.g. notify the assigned user when a Lead is created), then exercise Quick Add to create a Quote from the dashboard. That single flow touches migration, config, queue, and the new UI component, so it's the fastest way to validate the upgrade end to end.
Quick Add with quotes. Quick Add is a write path with a UI shell. The pattern that scales is to keep your business logic out of the controller: register or extend the action/request pair the package exposes, put validation in a FormRequest, and dispatch a domain event (QuoteCreated, LeadCreated) from the action. For quotes specifically, resolve the parent (Lead/Person) via route model binding or a hidden field, then recalculate line totals server-side — never trust a client-supplied total.
// app/Actions/CreateQuoteFromQuickAdd.php
public function handle(QuickAddQuoteData $data): Quote
{
return DB::transaction(function () use ($data) {
$quote = $this->quotes->createFor($data->subject(), $data->lines());
event(new QuoteCreated($quote));
return $quote;
});
}
Notifications. Follow Laravel's native notification contract rather than the package's internal mailer, if a choice exists — it gives you via(), ShouldQueue, and Notifiable for free. Queue them, use afterCommit() so a rolled-back quote doesn't emit a phantom notification, and expose per-user channel preferences in your own settings screen rather than editing vendor views.
public function via(object $notifiable): array
{
return $notifiable->wantsEmail('quotes') ? ['mail', 'database'] : ['database'];
}
Dashboard data filter. Treat the new filter as a DTO → query-scope pipeline. Build a small DashboardFilter value object from the request, then apply it through named scopes on your repository. This keeps the filter reusable from Livewire, API endpoints, and tests. Cache aggregate widgets keyed by a hash of the filter (Cache::remember("dash:{$filter->hash()}", 300, ...)) and bust on the events you already dispatch.
Mega search. The per-section record count is the most useful addition — it lets the modal show "Leads (42)" before the user scrolls. Implement it as two cheap queries per section: a count() with the same constraints, and a limit(N) fetch for the preview rows. Authorize per section, not once at the controller, and apply a ->limit() and a select-list of columns so the modal stays fast on large tables.
Lead Create/Update Product (#2682). After upgrading, add a regression test around the pivot sync: creating a lead with products, then updating the quantity/price, asserting both the pivot row and the derived lead total. This is a classic place where sync() vs syncWithoutDetaching() semantics silently drop rows.
Version discipline. Stay on 2.2.x with a caret constraint only if you have CI that runs your own suite against the package. Patch releases labelled "[fixed] Resolved Issues" are the ones that change behaviour quietly.
--force on config will discard your customizations. Publish to a temp tag or diff manually; the notifications and search keys are new and need merging by hand.users table, ensure it runs after your own auth migrations. If you use UUIDs or a non-default user model, check the foreign key definition before running in production.name, email, title). Consider caching counts for a short TTL.web middleware group. Add throttle:60,1 at minimum; throttle:search if you've defined one.afterCommit(), a failed quote save still sends the email. Also ensure notifications table exists before enabling the database channel, or via() will throw at runtime.decimal:2 casts and integer minor units. The Quick Add path makes it easy to introduce a float somewhere; assert totals in a unit test.$fillable or added a FormRequest, which can invalidate a package-level override you'd written.$guarded = [], unescaped Blade output in custom widgets, and any route you've added that bypasses the package's middleware.php artisan about to confirm the provider and config are loaded, Telescope for the search query storm, php artisan package:discover after composer changes, and Log::channel('daily') — vendor packages frequently log to the default channel.@stack/component overrides over view publishing, and container bindings over class_alias. Overriding controllers directly is the fastest path to a painful next upgrade.How can I help you explore Laravel packages today?