Revision: rebuilt around a worked CRM scope, data ownership, permissions, migration and acceptance checks.
Build a custom CRM when a specific business workflow justifies owning software. Start by describing that workflow, testing whether an existing product can support it, and identifying who will maintain the result. Laravel provides application building blocks; your team still has to define what a customer, an opportunity and an authorized action mean.
This guide uses a hypothetical service business to show how to build a CRM from scratch without turning the first release into an accounting system, marketing suite and project management platform. It is a planning example, not a report of a client deployment.
Decide whether to buy, configure or build
Write down five real activities, such as assigning an enquiry, logging a conversation, preparing a proposal, handing over a won deal and exporting a pipeline report. Try those activities in a shortlisted product with representative sample data. Include permissions, imports and exports in the trial; a feature appearing on a pricing page does not establish that it fits your process.
| Approach | A useful fit | What to establish first |
|---|---|---|
| Buy an existing CRM | Your sales process fits its records, stages and access controls. | Test daily tasks, data export, required integrations and the full subscription scope. |
| Configure or extend a product | Most of the workflow fits, with a few extra fields, reports or connections. | Identify extension limits and who maintains customizations when the product changes. |
| Build a custom CRM | Important approval rules, data relationships or operational handovers remain awkward after a practical trial. | Name the business owner, maintenance budget and acceptance criteria for the first release. |
Compare total ownership over the same period: implementation, data cleanup, training, hosting, support and future changes. A custom CRM avoids some product constraints but creates a software maintenance obligation. If the problem is inconsistent data entry or an undefined sales process, agree the process before automating it.
Work through one small service-business example
Assume a consultancy has six salespeople and one manager. Enquiries arrive through a website form and email. Salespeople record companies and contacts, own deals, set a next action and move qualified opportunities to proposal. A manager reviews the pipeline and approves the handover when work is won.
The first release has company and contact records, one pipeline, activities, assignments, a CSV import and three reports: open deals by stage, overdue next actions and wins within a chosen period. The existing accounting application continues to own invoices. Full mailbox synchronization, campaign automation and a customer portal stay outside this example's first release.
A meaningful completion target is: the manager can trace a won deal from its original enquiry to an approved handover, identify its owner and see what happened next. That is more useful than measuring progress by the number of screens delivered.
Separate customer companies from the account using the CRM
In this model, a workspace is the organization using the application; a company is one of its prospects or customers. The example begins with one workspace. If the product later serves multiple independent businesses, each workspace becomes a tenant boundary. A customer company must not accidentally become that boundary.
| Record | Example fields and relationships | Boundary or rule |
|---|---|---|
| Workspace | Name; account status. | Owns the CRM records and configuration. |
| User and membership | User identity; workspace, role and active status on membership. | A login identity may have separate memberships. A role applies within its workspace. |
| Company | Workspace, name, website and source reference. | A prospect or customer; its contacts and deals must belong to the same workspace. |
| Contact | Workspace, company, name, email and phone. | A person at a company; an email address alone is not a reliable universal identity. |
| Deal | Workspace, company, primary contact, owner membership, stage, value and currency. | The owner must be an active member of that workspace. Store value and currency together. |
| Activity | Workspace, deal, assigned member, type, due time and completion time. | Tracks a call, note or next action; it is separate from the system's change history. |
| Stage change | Workspace, deal, previous stage, new stage, actor, time and reason. | Records transitions according to an explicit audit and retention policy. |
Eloquent relationships can express these connections, but they do not decide which relationships are valid for your business. Use database constraints where appropriate and application checks to reject cross-workspace references. Adding a workspace column is only one part of isolation.
Keep source identifiers for imported records. Agree normalization and matching rules before adding uniqueness constraints. Two contacts sharing a reception email should not be silently merged. For reports, define whether a date filter means creation, expected close or actual close, and avoid adding different currencies without an explicit conversion rule.
Treat pipeline changes as business actions
For this example, use New, Qualified, Proposal, Won and Lost. Moving to Qualified requires a named owner and a recorded next action. Moving to Proposal requires a proposal reference. Won requires manager approval and a handover owner; Lost requires a reason. Reopening a closed deal is a separate manager action with a recorded explanation.
Validate these rules on the server, including imports and APIs. A draggable board is an interface to the rules, not their enforcement. If two users change a deal at the same time, detect the conflict or serialize the change so a stale screen cannot silently overwrite an approval.
Use a database transaction for related local writes, such as the stage update and its history record, with an appropriate concurrency strategy. External messages require separate recovery handling. Laravel's after-commit queue dispatch can defer a job until the transaction commits; it does not by itself guarantee that a remote action happens exactly once.
Design access at the record and workspace level
In the example, salespeople can update their assigned deals; the manager can reassign deals and approve wins. Everyone's access stays within the workspace. Decide separately who can export customer data, merge records, delete attachments or change integration settings. “Administrator” should have a defined scope.
Laravel policies and gates organize authorization checks. Your application must implement and invoke them; login does not establish record access. Scope list queries, search results, reports and exports as well as individual record endpoints. Resolve the workspace from a verified membership rather than trusting an arbitrary identifier sent by the browser.
Carry the same boundary into queued jobs, cache keys and file access. Recheck relevant permissions before delayed sensitive actions; a membership may have been removed since the job was created. Test a second workspace even if the pilot has only one. Laravel does not automatically provide a complete tenant-isolation or audit system.
Rehearse the import and reconcile the result
Assign a business owner to the source spreadsheets. Map columns, dates, currencies, owners and pipeline stages before importing. Keep the original export unchanged, identify its version and record how every rejected or merged row was handled.
- Dry run: validate a copy without writing production records. Report missing owners, invalid stages, duplicate candidates and unresolved relationships.
- Resolve: review ambiguous matches with the business owner. Do not merge customer histories on a similar name alone.
- Import: use stable source identifiers and an import-run record so rerunning the same input has a defined result.
- Reconcile: compare source and destination counts, accepted and rejected rows, deal totals by currency, ownership and sample histories.
- Cut over: agree when the old system stops accepting changes, how final changes are captured and what would trigger a rollback.
For example, a hypothetical 240-row contact file might produce 220 new contacts, 12 updates and eight rows held for review. Those outcomes account for all 240 input rows; they are not 240 newly created contacts. Repeat the run and prove the agreed result without duplication. Reconcile deal values and links separately from row counts.
Give integrations an owner and a recovery path
Start with the enquiry form and explicit email logging for this pilot. If mailbox synchronization is later required, scope provider authorization, shared-mailbox visibility, attachment handling, reconnect behavior and what happens when a user leaves. Agree which system owns each field before enabling two-way updates.
Keep credentials on the server and out of source control, browser bundles and logs. Laravel's configuration guidance explains environment-file security. Per-user integration tokens also need protected storage, restricted access, revocation and a rotation process; storing them is not equivalent to securing them.
Verify incoming events using the provider's documented mechanism. Record provider event identifiers within the correct integration account, and make repeat delivery safe. An idempotency rule should prevent a retried enquiry from creating another deal. Where a provider supports idempotency keys, use them for outgoing operations; otherwise reconcile uncertain outcomes before resending.
Set bounded retries and timeouts, distinguish temporary failures from invalid credentials, and show failed work to an operator. Laravel's HTTP client does not throw on HTTP 4xx or 5xx responses by default, so explicitly inspect or raise errors. A queue job finishing without an exception is not proof that the provider accepted the request.
If these tasks use Redis queues, our Laravel Horizon queue guide explains how to check worker configuration, delayed work and failed attempts. Keep the CRM's business outcome visible as well: an empty queue does not prove that every enquiry reached its intended destination.
Turn the scope into acceptance checks
Use the same sample records throughout development, review and user training. Include failures and prohibited actions, not just the successful screen journey.
- Isolation: a member cannot read, update, export or download another workspace's records, including by substituting identifiers.
- Ownership: a salesperson cannot approve a win or assign a deal to an inactive or unrelated member.
- Transition: an invalid move leaves both the deal and history unchanged; concurrent moves follow the agreed conflict rule.
- Import: the 240-row example reconciles, held rows stay visible and a rerun creates no unintended duplicates.
- Integration: duplicate events create one enquiry; a timeout produces a recoverable status instead of an invisible failure.
- Reporting: stage counts, close-date filters and currency totals match a manually checked fixture.
- Recovery: restore a backup in an isolated environment and verify records, attachments and access rules.
Pilot the workflow and hand over its operation
Begin with a small group handling real work. Record where they leave the CRM to finish a task, where ownership is unclear and which reports they actually use. Separate defects from new scope, then decide whether the next improvement is software, data cleanup or a clearer business rule.
Handover should include repository and hosting access, deployment instructions, the data model, role rules, integration ownership, import reconciliation, monitoring and a tested recovery procedure. Assign responsibility for failed jobs, dependency updates and support. Audit records need an intentional retention policy and access restrictions; general application logs are not a substitute.
Our Corcava case study provides a separate product example of connected business workflows. The hypothetical design above is not a description of Corcava's internal architecture.
For help defining a project, our CRM development service starts with workflow, data and integration scope. If the CRM will extend an existing application, our Laravel and PHP development service covers that starting point. Bring a sample workflow, representative data and the current tools so the first release can be defined around work your team needs to complete.
For the staff-facing part of a CRM, our Filament admin-panel guide turns a proposed report-review task into resource permissions, a controlled retry action and concrete acceptance cases.
