Customer Relationship Management
Modular CRM logic for Laravel. Manage contacts, companies, leads, opportunities, and pipelines through a clean fluent API — pure business logic, no UI, no bloat.
Getting Started
Installation
$ composer require obelaw/ium-crm
Publish Configuration
$ php artisan vendor:publish --tag=ium-crm-config
Run Migrations
$ php artisan migrate
Requirements
- • PHP 8.2+
- • Laravel 10+
- • MySQL 8.0+ or PostgreSQL 14+
Contacts
Contacts are the core entity in IUM-CRM. They can represent individuals or companies, and can be tagged, filtered, and linked to companies via roles.
Create a Contact
ium()->crm()->contacts()->create([
'type' => 'individual', // individual | company
'first_name' => 'Ahmed',
'last_name' => 'Al-Omari',
'email' => '[email protected]',
'phone' => '+966500000000',
'tags' => ['vip', 'wholesale'],
]); Find, Update & Delete
// Find by ID
ium()->crm()->contacts()->find('CON-001');
// List with filters
ium()->crm()->contacts()->list(tag: 'vip', type: 'individual');
// Update
ium()->crm()->contacts()->find('CON-001')->update([
'phone' => '+966511111111',
]);
// Attach to company
ium()->crm()->contacts()->find('CON-001')
->attachToCompany($company, role: 'manager');
// Delete
ium()->crm()->contacts()->find('CON-001')->delete(); Companies
Companies represent organizations in your CRM. You can associate multiple contacts to a company and retrieve all linked opportunities.
Create a Company
ium()->crm()->companies()->create([
'name' => 'Advanced Technology Co.',
'domain' => 'tech-advanced.com',
'industry' => 'technology',
'size' => '50-200',
'country' => 'SA',
'tags' => ['enterprise'],
]); Retrieve Related Data
// Get all contacts in a company
ium()->crm()->companies()->find('COMP-001')->contacts();
// Get all opportunities for a company
ium()->crm()->companies()->find('COMP-001')->opportunities();
// Update
ium()->crm()->companies()->find('COMP-001')->update([
'size' => '200-500',
]); Leads
Leads track potential customers at the top of your funnel. Score them, qualify using BANT criteria, and convert them directly into pipeline opportunities.
Create & Qualify
// Create
ium()->crm()->leads()->create([
'contact_id' => $contact->id,
'source' => 'website', // website | referral | cold-call | social
'score' => 75, // 0–100
'notes' => 'Interested in Enterprise package',
]);
// Qualify (BANT)
ium()->crm()->leads()->find('LEAD-001')->qualify([
'budget' => 50000,
'authority' => true,
'need' => true,
'timeline' => 'Q3-2026',
]); Convert & Disqualify
// Convert to Opportunity
ium()->crm()->leads()->find('LEAD-001')
->convert(pipeline: 'default');
// Disqualify
ium()->crm()->leads()->find('LEAD-001')
->disqualify(reason: 'no-budget');
// List with filters
ium()->crm()->leads()->list(status: 'new', source: 'website');
ium()->crm()->leads()->list(score: ['min' => 60]); Lead Statuses
- •
new— Just created - •
contacted— Reached out - •
qualified— Meets criteria - •
disqualified— Not a fit
Lead Sources
- •
website— Website form - •
referral— Word of mouth - •
cold-call— Outbound call - •
social— Social media
Opportunities
Opportunities represent active deals in your pipeline. Move them through stages, track deal value and probability, and close them as won or lost.
Create an Opportunity
ium()->crm()->opportunities()->create([
'contact_id' => $contact->id,
'pipeline_id' => 'sales-pipeline',
'stage' => 'discovery',
'value' => 25000.00,
'currency' => 'SAR',
'probability' => 60,
'expected_at' => '2026-09-01',
]); Manage Stages & Close
// Move stage
ium()->crm()->opportunities()->find('OPP-001')
->moveTo(stage: 'proposal');
// Close won
ium()->crm()->opportunities()->find('OPP-001')
->close(outcome: 'won');
// Close lost with reason
ium()->crm()->opportunities()->find('OPP-001')
->close(outcome: 'lost', reason: 'chose-competitor');
// Attach PIM products
ium()->crm()->opportunities()->find('OPP-001')
->attachProducts([
['sku' => 'PKG-ENTERPRISE', 'qty' => 1, 'price' => 25000],
]);
// Link OMS order
ium()->crm()->opportunities()->find('OPP-001')
->linkOrder('ORD-2026-001'); Pipelines
Pipelines define the stages that opportunities progress through. Each stage carries an order and probability weight for accurate forecasting.
Create a Pipeline
ium()->crm()->pipelines()->create([
'name' => 'Sales Pipeline',
'stages' => [
['name' => 'Discovery', 'order' => 1, 'probability' => 20],
['name' => 'Proposal', 'order' => 2, 'probability' => 40],
['name' => 'Negotiation', 'order' => 3, 'probability' => 70],
['name' => 'Closed Won', 'order' => 4, 'probability' => 100],
['name' => 'Closed Lost', 'order' => 5, 'probability' => 0],
],
]);
// Get all opportunities in a pipeline
ium()->crm()->pipelines()->find('sales-pipeline')
->opportunities();
// Filter by stage
ium()->crm()->pipelines()->find('sales-pipeline')
->opportunities(stage: 'negotiation'); Activities
Activities record every customer interaction and allow your team to schedule future follow-ups. Link them to contacts and opportunities for full context.
Log & Schedule
// Log a past activity
ium()->crm()->activities()->log([
'type' => 'call', // call | email | meeting | task | note
'contact_id' => $contact->id,
'opportunity_id' => $opp->id,
'note' => 'Interested in offer, requesting discount',
'duration' => 15,
'occurred_at' => now(),
]);
// Schedule a future activity
ium()->crm()->activities()->schedule([
'type' => 'meeting',
'contact_id' => $contact->id,
'opportunity_id' => $opp->id,
'title' => 'Solution Presentation',
'scheduled_at' => '2026-06-01 10:00:00',
'assigned_to' => $userId,
]); Query Activities
// Get activities for a contact
ium()->crm()->activities()
->forContact($contact)
->ofType('call')
->get();
// Get pending tasks for a user
ium()->crm()->activities()
->pending()
->assignedTo($userId)
->get(); Activity Types
call — Phone call • email — Email • meeting — Meeting • task — Task • note — Note Segments
Segments group contacts dynamically using composable filter rules. Use them for targeted campaigns, bulk tagging, or integration with WMS stock-level data.
Create a Segment
ium()->crm()->segments()->create([
'name' => 'Active VIP Customers',
'filters' => [
['field' => 'tags', 'operator' => 'contains', 'value' => 'vip'],
['field' => 'last_order_at', 'operator' => 'greater_than', 'value' => now()->subDays(30)],
['field' => 'total_spent', 'operator' => 'greater_than', 'value' => 10000],
],
]);
// Get contacts in segment
ium()->crm()->segments()->find('SEG-001')->contacts();
// Bulk tag / untag
ium()->crm()->segments()->find('SEG-001')->tag('promotion-eligible');
ium()->crm()->segments()->find('SEG-001')->untag('promotion-eligible'); Supported Filter Operators
- •
contains— Field contains value - •
equals— Exact match - •
greater_than— Numeric / date comparison - •
less_than— Numeric / date comparison - •
in— Value in array
Reports
Built-in reporting covers pipeline performance, team activity, lead source attribution, and revenue forecasting — all via a fluent date-ranged query builder.
Pipeline Report
$report = ium()->crm()->reports()->pipeline('sales-pipeline')
->from('2026-01-01')
->to('2026-06-30')
->get();
// $report->total_value → 250,000 SAR
// $report->won_count → 12
// $report->lost_count → 5
// $report->win_rate → 70%
// $report->avg_deal_size → 20,833 SAR
// $report->avg_cycle_days → 45 Activity & Lead Source Reports
// Team activity report
ium()->crm()->reports()->activities()
->forUser($userId)
->from('2026-05-01')
->to('2026-05-31')
->get();
// Lead source attribution
ium()->crm()->reports()->leadSources()
->from('2026-01-01')
->to('2026-06-30')
->get();
// Revenue forecast
ium()->crm()->reports()->forecast()
->pipeline('sales-pipeline')
->quarter('Q3-2026')
->get(); OMS & PIM Integration
IUM-CRM integrates natively with IUM-OMS and IUM-PIM. Access order history, spending statistics, and product suggestions directly from the CRM fluent API.
Order History & Product Suggestions
// Get customer order history (OMS)
ium()->crm()->contacts()->find('CON-001')
->orders()
->get();
// Spending statistics
// $stats->total_spent → 75,000 SAR
// $stats->order_count → 8
// $stats->last_order_at → 2026-04-15
ium()->crm()->contacts()->find('CON-001')
->orders()
->stats();
// Suggest products from PIM
ium()->crm()->contacts()->find('CON-001')
->suggestProducts(limit: 5); Integration Map
| CRM Module | Integrates With | Purpose |
|---|---|---|
| Contacts | OMS | Link customer to orders |
| Leads | PIM | Show products to prospects |
| Opportunities | PIM | Attach products to deals |
| Opportunities | OMS | Link won deals to orders |
| Segments | WMS | Target offers by stock levels |
Full Method Chaining
// From lead creation to fulfilled opportunity
ium()->crm()
->leads()->create([
'contact_id' => $contact->id,
'source' => 'website',
'score' => 80,
])
->qualify([
'budget' => 50000,
'timeline' => 'Q3-2026',
])
->convert(pipeline: 'sales-pipeline')
->moveTo(stage: 'proposal')
->attachProducts([
['sku' => 'PKG-ENTERPRISE', 'qty' => 1, 'price' => 50000],
]);