Laravel CRM

repository·master·Indexed 19 days ago

https://github.com/venturedrake/laravel-crm

A versatile business management package for Laravel that can function as a standalone CRM or be integrated into existing SaaS and E-commerce applications. It includes features for sales and lead management, operations (invoicing, purchase orders), communication (chat, email/SMS marketing), and data management. The package provides a REST API (v2) powered by Laravel Sanctum, supporting multi-tenancy via X-Team-ID headers and comprehensive entity management for leads, products, organizations, and more.

Tokens
5.1K
Snippets
13
Records
26
Agent score
66%

What's inside laravel-crm

  1. Overview of Laravel CRM features

    master

    Laravel CRM provides a comprehensive suite of tools for managing business operations, including:

    • Sales & Leads: Sales leads management, deal management, quote builder (with accept/reject functionality), and Kanban boards.
    • Operations: Orders & Invoicing, Purchase orders, and Deliveries.
    • Communication: Web/In-app Chat, Email marketing, and SMS marketing.
    • Data Management: Customer and Contact database management, Products & Product Categories, Custom fields, and Activity Feeds/Timelines.
    • Organization: Notes, Tasks, File uploads, and Users & Teams.
    • Security: Secure registration/login and Roles & Permissions (powered by spatie/laravel-permission).
    • Integrations: Xero and ClickSend.
  2. How the Filament plugin interacts with the Core CRM

    master

    The venturedrake/laravel-crm-filament plugin is a UI wrapper that sits on top of the venturedrake/laravel-crm core. It does not duplicate business logic; instead, it delegates all data operations to the core services.

    Key Integration Points:

    • Data Persistence: Filament Resources use FormPayload to wrap form data, ensuring that existing core services (like LeadService) can access data using $request->property syntax.
    • Routing: Resources use getRecordRouteKeyName() to return external_id, ensuring compatibility with the core's identification system.
    • Lifecycle: Page hooks (like mutateFormDataBeforeCreate) delegate to core services to ensure that observers, number generation, encryption, and audit logs are triggered exactly as they are in the legacy UI.
    • Access Control: The plugin reuses existing Laravel Policies defined in the core package.
  3. Handle encrypted field searching in Filament tables

    master
    When LARAVEL_CRM_ENCRYPT_DB_FIELDS=true is set, standard Filament table searches will fail to find encrypted data. To support searching for Person or Organization names/details, you must implement logic equivalent to the core's SearchesEncryptableContacts within a Filament Concern. This ensures that the table search mechanism can correctly query encrypted columns.
  4. API Data Conventions and Formatting

    master

    When interacting with the API, adhere to the following data formats:

    • IDs: All entity IDs are UUIDs. The JSON id field is the entity's external_id. Lookup tables (e.g., industry, pipeline stage) accept integer IDs.
    • Money: All amount, price, and total fields are sent and returned as decimal dollars (e.g., 1500.50). The system handles conversion to cents internally.
    • Timestamps: Use ISO-8601 with timezone offset (e.g., 2026-07-15T10:00:00+00:00 or 2026-07-15T10:00:00Z).
    • Pagination: Use ?per_page=N (1–100, default 25). Responses use the standard Laravel pagination envelope (data, meta, links).
    • Sorting: Use ?sort=field for ascending and ?sort=-field for descending. Unknown columns are ignored. Default is -created_at.
    • Filtering: Supported on list endpoints: ?user_owner_id=<int> and ?active= (for products).
  5. Use the X-Team-ID header for multi-tenancy

    master

    If the host application has teams enabled (config('laravel-crm.teams', true)), you can control the request context using the X-Team-ID header.

    • Without X-Team-ID: Requests are scoped to the user's current_team_id.
    • With X-Team-ID: The request runs in the context of the specified team for list, store, update, and delete endpoints. The ID must be a team the user belongs to, otherwise the API returns 403 Forbidden with the message "You are not a member of the requested team.".

    Note on Single Resource Lookups: GET /{resource}/{uuid} resolves using the user's default current team due to Laravel's binding lifecycle. To find the correct UUID for a specific team, use the list endpoints with the X-Team-ID header.

  6. Prevent 403 errors by re-running the permission seeder

    master

    When upgrading venturedrake/laravel-crm, you must re-run the permission seeder before deploying the new code. This ensures that any new permission rows added in recent releases exist in your database. If these rows are missing, even Owner and Admin roles will receive 403 Forbidden errors because their Permission::all() grant was captured at the time they were originally seeded.

    Commonly missing permission families include:

    • crm monitors (Uptime / SSL monitoring)
    • crm features (Feature voting & feedback portal)
    • crm email-campaigns (Email marketing)
    • crm sms-campaigns (SMS marketing)
    • crm chat (Live chat)
    • crm activities (Activity timeline)

    Step 1: Update permissions and roles Run one of the following commands to create missing permission rows and re-grant them to stock roles. This is safe to re-run; it uses firstOrCreate and is additive.

    # Option A: Run the update command (recommended)
    php artisan laravelcrm:update
    
    # Option B: Run only the seeder without migrating
    php artisan db:seed --class="VentureDrake\LaravelCrm\Database\Seeders\LaravelCrmTablesSeeder" --force

    Step 2: For Multi-tenant installs ONLY If laravel-crm.teams is set to true, run this command after Step 1 to copy global roles and grants down to each team:

    php artisan laravelcrm:permissions

    Note: php artisan laravelcrm:permissions is not a substitute for Step 1. If you run it on a single-tenant install, it will exit without making changes.

    Verification You can verify permissions exist using Tinker:

    // Check if monitoring permissions exist (expect 4)
    Spatie\Permission\Models\Permission::where('name', 'like', '%crm monitors%')->count();
    
    // Check if Owner has all permissions
    Spatie\Permission\Models\Role::where('name', 'Owner')->first()->permissions->count();
    php artisan laravelcrm:update
  7. Make authenticated requests to the API

    master

    Pass your Sanctum token in the Authorization header using the Bearer scheme.

    Required Headers:

    • Authorization: Bearer <token>
    • Accept: application/json (Recommended)
    • Content-Type: application/json (Required for POST/PUT)

    Auth Management Endpoints:

    • GET /crm/api/v2/auth/me: Returns the authenticated user's details.
    • DELETE /crm/api/v2/auth/token: Revokes the current token.
    GET /crm/api/v2/leads HTTP/1.1
    Authorization: Bearer 1|abcdef1234...
    Accept: application/json
  8. Audit custom roles for view-only permission changes

    master

    This upgrade enforces server-side authorization on all mutating actions. Previously, custom roles with only view permissions (e.g., view crm leads without edit crm leads) could still perform edits via the UI because the server did not check permissions. Now, these actions will return 403 Forbidden and the corresponding UI buttons will be hidden.

    Before upgrading, audit your custom roles to ensure users who need to perform actions have the appropriate create, edit, or delete permissions assigned.

    Audit Command Use this Tinker command to list custom roles (excluding stock roles) and their current permissions:

    Spatie\Permission\Models\Role::where('crm_role', 1)
        ->whereNotIn('name', ['Owner', 'Admin', 'Manager', 'Employee'])
        ->get()
        ->mapWithKeys(fn ($r) => [$r->name => $r->permissions->pluck('name')]);
    php artisan tinker
  9. Integrate the Filament Plugin via Composer path repository

    master

    To develop or use the Filament v5 plugin alongside the core Laravel CRM, you must configure your host application (e.g., a Laravel 13 project) to treat both the core package and the Filament plugin as Composer path repositories. This allows both packages to be symlinked and editable live during development.

    In your host application's composer.json, define both the core CRM and the Filament plugin under the repositories key using the path type.

    "repositories": [
        {
            "type": "path",
            "url": "../laravel-crm"
        },
        {
            "type": "path",
            "url": "../laravel-crm-filament"
        }
    ]
  10. Configure the LaravelCrmPlugin in a Filament Panel

    master

    The LaravelCrmPlugin is used to register CRM resources, widgets, and modules within a Filament Panel. You can customize which modules are active using fluent method calls.

    In your PanelProvider (e.g., app/Providers/Filament/CrmPanelProvider.php), use the plugin() method to attach the CRM plugin. You can enable specific modules like Chat, Xero, or Marketing using the provided helpers.

    ->plugin(
        LaravelCrmPlugin::make()
            ->modules([/* custom module list */])
            ->withChat()
            ->withXero()
            ->withEmailMarketing()
            ->withSmsMarketing()
            ->brand('Your Brand Name')
            ->navigationGroup('CRM Management')
    )
  11. Install the Laravel CRM REST API (v2)

    master

    The API is included with the package. To enable it, you must configure Laravel Sanctum in your host application.

    1. Publish and run Sanctum migrations to create the personal_access_tokens table:

      php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
      php artisan migrate
    2. Add HasApiTokens to your host User model:

      use Laravel\Sanctum\HasApiTokens;
      
      class User extends Authenticatable
      {
          use HasApiTokens;
          // ...
      }
    3. Verify routes: Run php artisan route:list --path=crm/api to ensure the 8 resourceful entities and 3 auth routes are loaded.

    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
    php artisan migrate
  12. Access the CRM interface

    master
    Once installation is complete, you can access the CRM by navigating to the configured route prefix. By default, this is /crm. You can change this prefix by modifying the LARAVEL_CRM_ROUTE_PREFIX environment variable in your .env file. Log in using the owner credentials created during the php artisan laravelcrm:install process.