Adding a button to the List View in SuiteCRM

posted in: SuiteCRM | 0

It’s possible to add your own action menu items to the List view. By the end of this post you’ll be able to add your own menu items like this one:

Custom List View Button

In our case we’ll be adding this to the “Calls” list view.

First off we add the string for the menu item text. In this case “New action”. We place this into `custom/Extension/modules/Calls/Ext/Language/en_us.CustomMenuAction.php` (the `CustomMenuAction` part can be anything you like.



Next we create a new custom list view for the calls module and place this in `custom/modules/Calls/views/view.list.php` (customising views can be found in my SuiteCRM book).

This does the actual work of adding the button. This adds a new bit of HTML to the array `$this->lv->actionsMenuExtraItems`. SuiteCRM will then pick this up and add this to the list of action buttons.

In this case the button just points to a new entry point `myNewEntryPoint`. Adding entry points will be covered in a future post (if you are impatient you can always checkout my SuiteCRM book).

Chase the ace – The curse of the dealer

posted in: Games | 0


Chase the ace is a simple card game that I was taught when I was younger from my dad. Recently on holiday I was playing with some friends and for a few games it was always the dealer that was put out of the game first. We’d noticed this before and has dubbed it “The curse of the dealer”. I was curious to see if the curse had any basis or if it was just chance.

The rules

For those of you not familiar with Chase the Ace it is the simplest card game I know. Each player is dealt a card (the more players the better!). Play starts to the left of the dealer with each player deciding whether to keep his current card or to force the player on their left to swap with them. When play reaches the dealer they can choose to swap with the deck. After every player has had their turn the person (or persons) with the lowest card (Aces are low) is knocked out of the game. The next round starts again without the losing players until a player remains (or all players are knocked out).

Testing the curse

I created a simple python script to play a bunch of hands with 10 players and keep track of which player or players were knocked out first (the source of which can be found on GitHub.


The strategy played is pretty simple (so it may affect the outcome) and uses the following rules:

  • If a player swaps with us and we end up with a higher card then we always keep that card (since we are guaranteed to stay in).
  • If we have a card higher than a 7 keep it.
  • Otherwise swap.

Using 10 players for 10,000,000 hands gave the following results:

Position 0 1 2 3 4 5 6 7 8 9 Total
Loses 791547 1037209 1146774 1206951 1252666 1280194 1305464 1322220 1328504 1325231 11996760
% Loses 6.60 8.65 9.56 10.06 10.44 10.67 10.88 11.02 11.07 11.04



We can see that the dealer is indeed at a disadvantage and, in fact your odds of losing decreases as you get closer to early positions. I suspect that this is due to bad cards “bubbling up” through the positions. If you have a high card and are in later position you have a higher chance of losing it. I may revisit this code at some point and see if this code can be reused to generate an optional strategy.

Edit: Someone has pointed out that, in fact, it’s the second to last player that loses slightly more. I’m rerunning this with more games to see if this is chance or not – there may be a point where all players are equally disadvantaged.


SuiteCRM Push Notifications

posted in: SuiteCRM | 0

SuiteCRM Push Notifications is a package which adds push notifications using third parties as a possible workflow action. It currently only supports PushBullet.

Simply define your PushBullet API token for users that wish to receive notifications:


Then create a new workflow with the user as the recipient (careful not to accidentally bomb yourself with notifications!):

SuiteCRM Push Notifications is available on GitHub or on the SuiteCRM extensions directory.

SuiteCRM for Developers Released

posted in: SuiteCRM | 0


I work with SuiteCRM at my day job daily and have become quite experienced in it’s use, particularly customising and developing with SuiteCRM. However as a young project it lacks the wealth of resources that other projects have. Even the project from which it is forked could do better with documentation. There is docs, and some other good resources online but they take some searching for.

Enter SuiteCRM for Developers

I decided to write a book that covers some of the common development tasks that can be performed in SuiteCRM and provide a reference for making customisations. SuiteCRM for Developers is that book. It provides some of the knowledge that I have gathered from working with both SugarCRM and SuiteCRM and, hopefully, provides a good starting point for those wishing to develop with SuiteCRM.

Now released

I’m now pleased to announce that SuiteCRM for Developers has now been published on Leanpub. It’s available at an introductory rate of $14.99. I’m considering this version 1.0 and I plan to add additions and corrections. If there’s something you would like to see that I’ve missed or something that is wrong then feel free to Contact me.


SuiteCRM Custom Search Fields

posted in: SuiteCRM | 0


Sometimes you may want to add custom search fields to a module that do more than simply search a field. In this post we’ll be looking at how to add a custom search field which will allow searching for all accounts that have no associated contacts.

Adding the field

First off we create a copy of modules/Accounts/metadata/searchdefs.phpand place this in custom/modules/Accounts/metadata/searchdefs.php. We then add a new key to the $searchdefs ['Accounts']['layout']['basic_search']array which  will look something like:
We also need to add a language string for our new search field. This can be done by simply adding a new file at custom/Extension/modules/Accounts/Ext/Language/en_us.NoContactFilter.php:

This will give us the following:



Unfortunately, SuiteCRM displays our new search field as a dropdown rather than a checkbox, stay tuned for a future post on how to change this.


Adding the logic

Now we have a wonderful search dropdown on our Accounts list view. It doesn’t actually do anything however. Let’s change that.


We create a copy of modules/Accounts/metadata/SearchFields.phpand place this in custom/modules/Accounts/metadata/SearchFields.php in exactly the same manner as we did for searchdefs.php above. We add our new search field to the $searchFields['Accounts']  array.

It should look something like:

This creates a subquery filter type. Specifying a query type of format allows us to use {0} in our query to access the dropdown value. SuiteCRM will only display account ids that match what our subquery returns.

FROM accounts 
LEFT JOIN accounts_contacts ON ( = accounts_contacts.account_id AND accounts_contacts.deleted = 0)WHERE (NOT {0} AND IS NOT NULL) OR ({0} AND IS NULL)

We make use of this to force only accounts with contacts when “No” is selected (the NOT {0} AND IS NOT NULL part of the query) and only accounts with no contacts when “Yes” is selected (the {0} AND IS NULL part of the query).


Adding custom subqueries in this manner allows a huge amount of custom filters to be created. Have an idea for a custom filter? Have a better way of doing the above? Then let me know in the comments.

SuiteCRM Package Builder

posted in: SuiteCRM | 0

SuiteCRM package builder is a small PHP script which eases the pain of building a SuiteCRM package for installing changes to other instances. It simply requires a SuiteCRM install and a compliant manifest file.

This means you can build up the bulk of the package just by running something similar to:

suitecrmpackagebuilder /var/www/mySuiteCRMInstance/manifest.php /var/www/mySuiteCRMInstance/

It can be found on my GitHub page here: SuiteCRM Package Builder.

As always you should back up any instance before running code from a stranger on the internet.

BeanFactory Cache

posted in: SuiteCRM | 0


The BeanFactory is a great way to load and query for beans without using SQL.

For example we can load an Account with a known id:

Unexpected behaviour

However this method can cause some unexpected behaviour. Let’s look at the following example:


This produces the following output:

Enter the cache

So what is going on here?

Basically the getBean method is cached. getBean will cache at most 10 beans and drop some of the older entries based on usage. $acc2 is pulled from the cache and is therefore the same instance as $acc1. Any changes in one will be reflected in the other.

However when we load a bunch of beans our cached account drops out the BeanFactory Cache and when we fetch the bean into $acc3 we get a fresh instance from the database.