Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Crm Laravel Package

venturedrake/laravel-crm

Laravel CRM is a free, open-source, self-hosted CRM package for Laravel applications. It provides leads, contacts, accounts, deals, activities, notes, and customizable sales pipelines, plus modern Laravel authentication and Blade UI components to help you add CRM functionality quickly and easily.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Baseline. This supersedes the initial 2.4.7 assessment, which was established from a single patch release note with correspondingly limited confidence. 2.5.0 is a materially larger release — a new product-variations feature spanning schema, services, PDFs, email, portal, Xero and REST API, plus four behavioral fixes and two removals. Confidence in the change description is now higher (the notes enumerate schema, services, tests and edge cases in unusual detail), but confidence in the package as a whole remains bounded: we still have no full package review, no changelog beyond per-release notes, and no visibility into CI.

Architecture fit. Unchanged in shape, and the shape continues to hold. The package remains a conventional Laravel domain module: publishable config, service provider, laravelcrm:update Artisan command, settings middleware keyed on crm.settings-seeded.<version>, Livewire components for forms. 2.5.0 introduces no new architectural primitives — it extends existing ones:

  • Variations activate dormant schema. crm_product_variations, crm_product_prices.product_variation_id and the product_variation_id line columns already existed but were never read or written. 2.5.0 turns them on and adds two idempotent database/updates migrations for code, barcode, order, active, user_*_id, plus purchase-order line columns. This is a favorable pattern (additive migrations over a schema already anticipated) but it means a previously inert part of the database now becomes load-bearing.
  • A deliberate resolution seam. Variation→product/team validation is centralized in ResolvesProductVariation, and pricing in Product::unitPriceFor(), with presentation split across displayName() / displayCode() on line models. That is the right factoring for a TPM to note: the integrity rules live in one service and one model method rather than being duplicated across five line-item types and five PDF styles.
  • One new external boundary. XeroLineItem now composes variation name into Description and conditionally substitutes the variation SKU as ItemCode. This is the only place 2.5.0 reaches outside the app's own data model with new semantics.
  • Version identity remains the weak seam. The five-place, hand-maintained version string is unchanged. 2.5.0's own notes state config/package.php still read 2.4.7 — the exact defect recorded in our 2.4.7 assessment recurred on the very next release.

Integration feasibility. Medium, down from High. Still no new Composer dependencies and no changes required to host-application code, but this release is not a drop-in in the way 2.4.7 was:

  • Migrations are mandatory, not optional. Three migrations (two variation, one purchase-order line). Skipping them is not cosmetic as it was in 2.4.7 — it produces runtime SQL errors on the product form and on purchase-order line saves.
  • Removals are real, even if the surfaces were broken. The v1 /crm/customers routes, CustomerController, StoreClientRequest/UpdateClientRequest, the customers/index view, and the entire Product Attributes surface (ProductAttribute model, policy, controller, routes, views, two Settings nav entries, lang keys) are gone. These errored for most users (#93, #53), so end-user impact is likely near zero — but any host app that referenced laravel-crm.customers.* route names, extended CustomerController, or used the ProductAttribute model will hard-fail with class-not-found or missing-route errors. A minor version carrying removals is a semver deviation worth recording regardless of how dead the code was.
  • Two fixes change write semantics, not just reads. Purchase-order updates now diff the submitted line set — matched lines update, new lines add, and lines no longer submitted are removed. Person/organization saves now write a related-contacts link. Both are behavior changes that can affect stored data.

Technical risk. Moderate, concentrated in data-mutation and external-sync surfaces rather than in code quality. The release is unusually well-tested — eight named feature test files covering the variation feature alone (model, two Livewire forms, deals, conversions, PDFs, Xero, API v2, migrations) plus dedicated tests for the PO schema fix, restored-user columns, and person/organization linking. That is the strongest single signal in these notes and materially lowers the risk of the new code being wrong. The residual risks are:

  1. Version-bump discipline has now failed twice consecutively. 2.4.6 shipped stale, 2.4.7's notes flagged it, and 2.5.0's notes confirm config/package.php again read 2.4.7 at build time. The consequences the notes spell out — banner compares against the previous release, "database behind code" check misreports, and the version-keyed seeding flag fails to re-arm — are the ones we predicted. Nothing indicates a CI guard was added. This is a process risk with a known, cheap fix that is not being applied.
  2. Purchase-order line deletion on update. Correcting update() to read products instead of the never-sent purchaseOrderLines is right, and scoping matches to the PO being edited is right. But "removes lines that are no longer submitted" is a destructive default. Any caller — UI bug, API integration, or script — that submits a partial line set will now delete lines rather than silently no-op as before. The previous behavior was data loss in the other direction, so this is a net improvement, but it converts a silent failure into a destructive one.
  3. Price scoping changes existing computed values. Product::productPrices() now returns product-level rows only, and ProductPrice::scopeDefault() excludes variation prices (and previously compared currency against a Setting model rather than its value). This is a genuine bug fix. Its side effect: on any install where a price row would now be classified as a variation price, getDefaultPrice() can return a different value — or nothing — after upgrade. Low likelihood, non-zero, and hard to detect without a data check.
  4. Xero ItemCode and Description semantics shift. Sending the variation SKU as ItemCode only when a synced Xero item already carries that code is a sensible guard against creating orphan items. It also means invoice lines for the same parent product can reference two different Xero item codes depending on sync history. Anyone reconciling Xero against the CRM by item code will see new patterns.
  5. Person/organization links accumulate. The fix is welcome (#94) and the dedupe guard is stated, but "changing the person or organization on a record keeps the old link" means re-picks grow the related-contacts list rather than moving the link. If there is no unlink UI, this is a quiet data-growth path.
  6. Removals in a minor. No deprecation cycle is announced. The removed code was broken, so this is defensible — but it sets a precedent that host apps extending package internals may be broken by a minor bump.

Key questions.

  • Is the version constant now CI-enforced — a test asserting the config value matches the latest git tag or composer.json? This has failed on two consecutive releases; without a guard it will fail again.
  • Semver policy: are removals permitted in minor releases, and is there a deprecation window? Concretely, did anyone reference laravel-crm.customers.*, CustomerController, or ProductAttribute — and if so, what is the migration guidance?
  • Are all three migrations (two variation, one PO line) idempotent and index-bearing — specifically an index on variation code/barcode (the products index now searches by variation SKU) and on product_variation_id line columns?
  • Was crm_product_variations ever populated in the field, e.g. via the V1→V2 upgrade path? If so, what data surfaces now that code reads those rows for the first time?
  • For Product::productPrices(): is there a verification query or backfill to identify products whose default price changes after upgrade?
  • Purchase-order update: what defines "submitted"? Does the API v2 expose PO line updates, and do those callers send complete line sets? Is there any guard against an empty payload wiping all lines?
  • Person/organization linking: is there a UI affordance to remove a related contact? What bounds the growth of that list over repeated edits?
  • Xero: confirm the fallback to parent item code when no synced item matches the variation SKU, and whether any downstream reconciliation keys off Description.
  • Is there now a consolidated changelog or a 2.4.x → 2.5.0 upgrade guide, or is release history still only discoverable per-release?

Integration Approach

Stack fit. Unchanged prerequisites — Laravel 10/11/12, Livewire for the form layer, Composer installation, and a stable APP_KEY (encryption is now more central, not less: variation pricing and display logic sit on the same model layer as the encrypted fields). One addition: the database user needs DDL rights at deploy time, because this release ships migrations that must actually run. Hosts on a migration-by-CI-pipeline model should confirm the database/updates path is included in that pipeline — the prior 2.4.7 upgrade could be completed without touching schema, and this one cannot.

Migration path. Larger than 2.4.7 and should not be treated as a hotfix. Recommended order:

  1. Back up, then upgrade in non-production. composer require <vendor>/laravelcrm:2.5.0, review the lockfile diff for transitive changes. Confirm nothing in the host app references the removed CustomerController, laravel-crm.customers.* route names, StoreClientRequest/UpdateClientRequest, or any ProductAttribute class.
  2. Run php artisan laravelcrm:update so the three migrations apply and the db_version marker advances to 2.5.0. Do this before exercising the UI — the product form and purchase-order saves will fail without the new columns.
  3. Clear config cache and let the seeding flag re-arm. crm.settings-seeded.2.4.7 will not match 2.5.0, which is the intended re-seed. Refresh config:cache explicitly; an opcode-cached deploy can otherwise serve the old constant.
  4. Data verification pass on a production snapshot before cutting over: (a) products whose default price resolves differently under the new productPrices() scope; (b) any pre-existing rows in crm_product_variations or product_variation_id columns that will now be rendered; (c) purchase orders currently holding lines, to confirm the new diff-and-delete update path behaves on real data.
  5. Restart workers and queues per standard deploy practice, then smoke-test in this order: product variation CRUD → variation select on a deal line and a converted quote/order/invoice → PDF/email/portal rendering of a variation line (all five PDF styles) → purchase-order create and edit with lines → restoring a soft-deleted product and confirming user_restored_id is set and user_deleted_id cleared → saving a lead with both a person and an organization and confirming the cross-link appears on both show pages → one Xero invoice sync with a variation line.
  6. API consumers: verify product payload parsers tolerate the new variations key, and exercise POST/PUT/DELETE /products/{product}/variations plus the 422 path for a variation belonging to another product or team.

Compatibility. Additive for the API (new sub-resource, new line_items field, new variations key on product responses) — strict schema validators on the consumer side are the only likely breakage. The removals are the compatibility edge: functionally dead code, but code-level breaking if referenced. The variation feature is explicitly scoped so that a product with no variations behaves exactly as before, which bounds regression risk for the majority of installs. The trait-hook extension point from 2.4.7 remains supported; no reversal is announced.

Sequencing. Do not bundle. 2.5.0 combines schema changes, a new feature across nine surfaces, four behavior fixes, and two removals — that is too much to attribute cleanly if something regresses. Land it as its own release, in a window where a rollback is tolerable, and stage it: migrations plus backend first in a staging environment, UI verification second, Xero sync verification last (it is the only irreversible external side effect). If the host is mid-migration on Livewire or on the encryption feature, finish that first, as with 2.4.7. Teams that have not yet taken 2.4.7 can go directly to 2.5.0 — the version marker and seeding flag advance to 2.5.0 either way, and there is no intermediate step to honor.

Operational Impact

Maintenance. Low steady-state burden continues — no new services, jobs or infrastructure. Two standing items, one of them now overdue:

  • Enforce the version constant in CI. This is the third release in a row where the hand-maintained string is the weak point, and 2.5.0's notes confirm it was stale at build time again. A single test asserting config('package.version') matches the git tag or composer.json retires this class of defect permanently. Until then, the release checklist must cover all five locations: config/package.php, SystemCheckService::normalisedVersion(), the db_version marker, the UpdateController banner, and the seeding flag.
  • Keep a schema-drift check in the deploy pipeline. The purchase-order line bug — create() writing comments and order_product_id to columns no migration ever added, passing because no test saved a PO with lines — is exactly the failure a staging deploy against a real database catches. It is also a reminder that the test suite's schema and a production schema had diverged; a periodic schema-diff between test and production snapshots is cheap insurance.

Support. Expect a broader and longer tail than 2.4.7, in four distinct buckets:

  • Purchase-order edits. Users who previously made line edits that silently vanished will now see those edits apply — and, if their client submitted a partial line set, see lines disappear. Triage guidance: "removed lines were not submitted by the form" is the first question. Highest-severity bucket because it can delete data.
  • Variation pricing. The rule is "variation price in the document currency, else the product price," and a variation with no price sells at the product price. Multi-currency teams will hit this and read it as a bug. A one-paragraph help note with a worked example converts most of it.
  • Xero item codes. Invoice lines can now reference the variation SKU or fall back to the parent item code depending on whether a synced Xero item carries that code. Document the rule explicitly for finance users; it will otherwise surface as "why did this line post differently."
  • Removed routes. /crm/customers now 404s instead of throwing Call to undefined method ... sortable(). Bookmarked links get a cleaner failure, which is an improvement, but support should have a scripted "use People and Organizations instead" response ready.

Person/organization linking is likely to generate positive support contact rather than negative — the link appearing on both show pages is the visible outcome of a bug users had stopped reporting.

Scaling. Modest but no longer negligible. Three things to watch:

  • Line-item rendering cost. Each line now resolves an optional variation plus a currency-specific price via unitPriceFor(). On documents with many lines, and on list/index pages, this is a candidate for N+1 unless variation and price relations are eager-loaded. Worth a query-count check on a representative order before and after.
  • Variation SKU search. The products index now matches on variation SKU, which means a join or subquery against crm_product_variations. Confirm the migration adds an index on code (and barcode if searched) — without one this degrades as variation volume grows.
  • Related-contacts growth. Links persist across re-picks, so related-contact lists on long-lived records grow monotonically. Small per-record, but it touches show-page rendering; if there is no unlink path, plan for one eventually.

Everything else — the seeding flag (per-version, not per-user), the observer fixes, the API sub-resource authorization (delegated to the parent product, so no new permission surface) — has no scaling implication.

Failure modes. Five, ordered by severity:

  • Migrations not run — product form and purchase-order line saves fail with SQL errors on missing columns. Not self-healing; requires the laravelcrm:update run. This is the highest-severity failure mode in the release and the one most likely to occur on a pipeline that doesn't execute the package's updates.
  • Purchase-order update removes lines — a partial submission deletes lines that exist. Recoverable only from backup or by re-entering. Mitigate by reviewing the form's submitted set and any API caller before enabling for users.
  • Variation data surfaces unexpectedly — if crm_product_variations or product_variation_id was ever populated outside this code path, existing documents may render a variation where none was previously shown, and getDefaultPrice() may resolve differently. Detectable with the pre-upgrade data verification query; not self-healing.
  • Stale config cache or skipped version marker — banner and system check misreport, seeding pass fails to re-arm. Cosmetic and self-healing on the next correct run, exactly as in 2.4.7. Same mitigation: banner check in the post-deploy smoke test.
  • Xero line composition drift — a variation SKU that matches no synced item falls back to the parent item code by design; if that fallback is misunderstood, finance may chase a phantom mapping error. Failure is a reconciliation question, not corrupt data, and it is external to the CRM so rollback is not available — verify on a single invoice first.

Ramp-up. Higher than 2.4.7 but still contained. A developer fluent in Laravel packages and Livewire needs roughly one to two days to be productive on this release: the variation model and its pricing rule, the ResolvesProductVariation integrity seam, the five line-item types and their conversions, the displayName()/displayCode() presentation split, the API sub-resource, and the Xero composition rule. Add half a day of QA orientation for the PDF/email/portal rendering paths, since those are visual and easy to under-test. The one concept a new team member must internalize is still the version-coupled chain — config constant → db_version marker → update banner → seeding flag — because it is now demonstrably the most common source of confusing "why is the banner still showing" debugging. Budget it as a 30-minute onboarding note, and treat it as a prompt to fix the root cause rather than document it a third time.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console