Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here

FlarePoint: Laravel-based free CRM [REVIEW]

Today I'm starting a series of reviews: will be trying and testing various Laravel-based open-source projects available on GitHub and elsewhere. First to check out - is a self-hosted CRM project called Flarepoint.


Other reviews in this series:

  1. FlarePoint: Laravel-based free CRM
  2. Invoice Ninja – Laravel-powered solution for better invoicing
  3. Attendize – event tickets selling system based on Laravel 5
  4. Ribbbon – project management system on Laravel 5.1 and Vue.js
  5. Faveo: impressive helpdesk system built on Laravel
  6. Confomo: Laravel-based website to meet Twitter friends at conferences

For those who don't know what CRM is - it stands for "Customer Relationship Management". Basically, it's a system to manage data of your clients, potential leads, tasks assigned to them for follow-up or other actions.

Flarepoint is a CRM built on Laravel 5.3 - launched quite recently, in July 2016. Its author is Casper Bottelet from Denmark.

Here's how Flarepoint CRM looks in action:

flarepoint-01

As you can see, it's a dashboard with all the functionality I had mentioned above.


Installation

Flarepoint is distributed as a full Laravel project for download and install on your server. That's exactly what I did myself - tested it on my local Homestead.

Installation went well, instructions are perfectly clear and simple. Just clone, run composer install, database migration/seeds and you're good to go. Well done.

Especially I liked that the system comes with ready-made seed files with data for Departments, Industries and other settings.

flarepoint crm database seeds

Usage

After installation, you can launch the application and see login screen.

flarepoint crm login screen

The first default user to login is admin@admin.com - admin123, provided in installation guide. Convenient.

We log in and see the same dashboard but empty.

flarepoint crm dashboard

And then, one by one, we can fill in the data for our clients.

flarepoint crm create client

In general, everything is straightforward. One thing I didn't like that "Create entry" actions were only in the main menu on the left, but there were no "create" buttons in client list, or any lists. But that's a minor issue, no big deal.

flarepoint crm menu

Laravel code

As I mentioned, Flarepoint comes as open-source project, so you can modify it however you want. So let's take a look what's underneath in the code. I usually start evaluating the codebase from routes file - in this case, since it's Laravel 5.3 - we look at routes/web.php file.

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| This file is where you may define all of the routes that are handled
| by your application. Just tell Laravel the URIs it should respond
| to using a Closure or controller method. Build something great!
|
*/
Route::auth();
Route::get('/logout', 'Auth\LoginController@logout');
Route::group(['middleware' =--> ['auth']], function () {
    /**
     * MAIN
     */
        Route::get('/', 'PagesController@dashboard');
        Route::get('dashboard', 'PagesController@dashboard')->name('dashboard');
    /**
     * USERS
     */
        Route::get('users/data', 'UsersController@anyData')->name('users.data');
        Route::get('users/taskdata/{id}', 'UsersController@taskData')->name('users.taskdata');
        Route::get('users/closedtaskdata/{id}', 'UsersController@closedTaskData')->name('users.closedtaskdata');
        Route::get('users/clientdata/{id}', 'UsersController@clientData')->name('users.clientdata');
        Route::resource('users', 'UsersController');
        /* ROLES */
        Route::resource('roles', 'RolesController');
    /**
     * CLIENTS
     */
        Route::get('clients/data', 'ClientsController@anyData')->name('clients.data');
        Route::post('clients/create/cvrapi', 'ClientsController@cvrapiStart');
        Route::post('clients/upload/{id}', 'DocumentsController@upload');
        Route::resource('clients', 'ClientsController');
    /**
     * TASKS
     */
        Route::get('tasks/data', 'TasksController@anyData')->name('tasks.data');
        Route::patch('tasks/updatestatus/{id}', 'TasksController@updateStatus');
        Route::patch('tasks/updateassign/{id}', 'TasksController@updateAssign');
        Route::post('tasks/updatetime/{id}', 'TasksController@updateTime');
        Route::post('tasks/invoice/{id}', 'TasksController@invoice');
        Route::resource('tasks', 'TasksController');
        Route::post('tasks/comments/{id}', 'CommentController@store');
    /**
     * LEADS
     */
        Route::get('leads/data', 'LeadsController@anyData')->name('leads.data');
        Route::patch('leads/updateassign/{id}', 'LeadsController@updateAssign');
        Route::resource('leads', 'LeadsController');
        Route::post('leads/notes/{id}', 'NotesController@store');
        Route::patch('leads/updatestatus/{id}', 'LeadsController@updateStatus');
        Route::patch('leads/updatefollowup/{id}', 'LeadsController@updateFollowup')->name('leads.followup');
    /**
     * SETTINGS
     */
        Route::get('settings', 'SettingsController@index')->name('settings.index');
        Route::patch('settings/permissionsUpdate', 'SettingsController@permissionsUpdate');
        Route::patch('settings/overall', 'SettingsController@updateOverall');
    /**
     * DEPARTMENTS
     */
        Route::resource('departments', 'DepartmentsController');


    /**
     * INTEGRATIONS
     */
        Route::resource('integrations', 'IntegrationsController');

        /* SLACK */
        Route::get('Integration/slack', 'IntegrationsController@slack');
    /**
     * NOTIFICATIONS
     */
        Route::get('notifications/getall', 'NotificationsController@getAll')->name('notifications.get');
        Route::post('notifications/markread', 'NotificationsController@markRead');
        Route::get('notifications/markall', 'NotificationsController@markAll');
    /**
     * INVOICES
     */
        Route::resource('invoices', 'InvoicesController');
        Route::post('invoice/updatepayment/{id}', 'InvoicesController@updatePayment')->name('invoice.payment.date');
        Route::post('invoice/reopenpayment/{id}', 'InvoicesController@reopenPayment')->name('invoice.payment.reopen');
        Route::post('invoice/sentinvoice/{id}', 'InvoicesController@updateSentStatus')->name('invoice.sent');
        Route::post('invoice/reopensentinvoice/{id}', 'InvoicesController@updateSentReopen')->name('invoice.sent.reopen');
        Route::post('invoice/newitem/{id}', 'InvoicesController@newItem')->name('invoice.new.item');
    /**
     * IMPORT AND EXPORT
     */
        Route::get('documents/import', 'DocumentsController@import');

    });

Again, everything is pretty simple - all actions hidden under auth middleware, and most of them are Resource controllers, except for additional action for every item.

We also see a few integrations (like Slack), import of documents and permissions management. All really useful.

Now, let's take a look at one random Controller - let's say, ClientsController.php:

class ClientsController extends Controller
{

    protected $users;
    protected $clients;
    protected $settings;

    public function __construct(
        UserRepositoryContract $users,
        ClientRepositoryContract $clients,
        SettingRepositoryContract $settings
    ) {
        $this->users = $users;
        $this->clients = $clients;
        $this->settings = $settings;
        $this->middleware('client.create', ['only' => ['create']]);
        $this->middleware('client.update', ['only' => ['edit']]);
    }
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        return view('clients.index');
    }

As we can see, Repository pattern is being used, and index() method just calls the view. So I assume there's something going on in JavaScript side - let's look at clients/index.blade.php view:

@extends('layouts.master')
@section('heading')

@stop

@section('content')

<table class="table wp-block-table table-hover">
<thead>
<tr>
  <th>@lang('client.headers.name')</th>
  <th>@lang('client.headers.company')</th>
  <th>@lang('client.headers.mail')</th>
  <th>@lang('client.headers.primary_number')</th>
  <th> </th>
  <th> </th>
</tr>
</thead>
</table>

@stop

@push('scripts')
<script>
$(function() {
    $('#clients-table').DataTable({
        processing: true,
        serverSide: true,

        ajax: '{!! route('clients.data') !!}',
        columns: [

            { data: 'namelink', name: 'name' },
            { data: 'company_name', name: 'company_name' },
            { data: 'email', name: 'email' },
            { data: 'primary_number', name: 'primary_number' },

             { data: 'edit', name: 'edit', orderable: false, searchable: false},


             { data: 'delete', name: 'delete', orderable: false, searchable: false},


        ]
    });
});
</script>
@endpush

Guess what - I was right, the data is served via Datatables package and with AJAX.


Conclusion

All in all, Flarepoint looks like a really good minimal CRM project - I can congratulate Casper on great work:

  • Useful and usable system
  • Clean and professional code
  • Simple-to-use and with proper documentation

You can also use Flarepoint as an example project to learn or improve your Laravel knowledge.

Some links once again:


Other reviews in this series:

  1. FlarePoint: Laravel-based free CRM
  2. Invoice Ninja – Laravel-powered solution for better invoicing
  3. Attendize – event tickets selling system based on Laravel 5
  4. Ribbbon – project management system on Laravel 5.1 and Vue.js
  5. Faveo: impressive helpdesk system built on Laravel
  6. Confomo: Laravel-based website to meet Twitter friends at conferences

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 67 courses (1172 lessons, total 43 h 18 min)
  • 90 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent New Courses