-
Notifications
You must be signed in to change notification settings - Fork 0
Customization
You can find documentation and step-by-step guide on how to customize EspoCRM.
- Extension Creation
- Make custom entities and fields "non-deletable"
- Calculate fields continuously without flowcharts
- Duplicate checking for custom fields
- Create global filters for all users
- Field validation with regex
- Export and import flowcharts, workflows and reports
- Fields Dynamic Logic
- Data retention flowcharts
- Using hooks
- Translations
Extensions for EspoCRM can be considered as pre-made templates that you can deploy very fast. This extension can include entities, fields, layouts, formulas and other settings related to entities. This also allows you to quickly copy over a (custom) data model from one instance (e.g. dev) to another EspoCRM instance (e.g. production). The company behind EspoCRM uses extensions for their offering of paid extra functionality.
The file structure of the extension package:
- manifest.json – a file that contains extension properties such as name and version;
- files/ – a directory that contains extension files;
- scripts/ – a directory that contains extension scripts. (optional)
NOTE: Extension Name can be configured in the manifest.json
There is more detailed information on the specifics in this repository
Prerequisite: a file manager that can handle SSH, for this purpose, WinSCP is recommended, but PuTTY can most probably also be used
Steps:
- Open WinSCP (right the VM (remote), left is your local machine) & login with VM credentials.
- Host name is the IP address
- Port number is 22
- If cannot access: check if VM is accessible from your IP address (Azure -> network -> set SSH IP address to your own).
- In /var/www/espocrm/data/espocrm/ find the custom folder. Here all the custom entities + layouts + formulas + labels are stored.
- Copy the whole custom folder to your local computer (drag and drop in WinSCP)
- Structure of the "custom" folder: a "manifest.json" file and a "files" folder.
- Now on your local computer
- Create a new folder called "files" and copy the entire "custom" folder in "files". (Don't use the "client" folder if that exists).
- Create a template manifest file (copy-paste the deh "manifest.json") and place it on the same folder level next to the "files" folder
- Zip the "files" folder and the "manifest.json" Upload the .zip to your new EspoCRM as an extension.
More extensive documentation can be found here. Note: the more extensive docs should be moved to this knowledge base in the future.
There are two ways you can deploy an extension onto your EspoCRM: manual deployment via the UI of EspoCRM or via the command line in the Virtual Machine. The easier and preferred way is to deploy it manually via the UI.
Open your espo CRM, as an Admin, and navigate to the extensions page. Click on choose file and select the ZIP
Once the Zip is selected click upload and you'll get this pop-up.
Click on Install and that should apply the changes to your espo.
Connect to the server where you are hosting EspoCRM via SSH, and navigate to:
/var/www/espocrm/data/espocrm$
If you list out the files in this directory, you should see the command.php file. This is what we can use to deploy the extension.
php command.php extension --file="path/to/extension/package.zip"
It's important to note, the path to the extension can be a local ZIP on the computer your're connecting to the VM from.
- to make an Entity non-deletable set
"isCustom": false
incustom/Espo/Custom/Resources/metadata/scopes/<MyEntity>.json
- to make a Field non-deletable set
"isCustom": false
underfields/<MyField>
incustom/Espo/Custom/Resources/metadata/entityDefs/<MyEntity>.json
If a field can be calculated with EspoCRM-compatible SQL expressions, you can configure it so that it will be calculated "at runtime", i.e. each time it is visualized in any layout, automatically. For example, to calculate age
from dateofBirth
in the entity cPersonAffected
, edit the age
field in .../Custom/Resources/metadata/entityDefs/cPersonAffected.json
as
"age": {
"type": "int",
"notStorable": true,
"readOnly": true,
"isCustom": true,
"select": "YEAR(NOW()) - YEAR(cPersonAffected.dateof_birth) - IF(MONTH(NOW()) < MONTH(cPersonAffected.dateof_birth) OR (MONTH(NOW()) = MONTH(cPersonAffected.dateof_birth) AND DAY(NOW()) < DAY(cPersonAffected.dateof_birth)), 1, 0)"
},
Click here
Click here
Click here
There is an easy way to quickly grab the existing flowcharts, workflow or reports (these are part of the Advanced Pack) from one instance and paste it to another instance. This can save a lot of time of manually creating and bug solving. Prerequisite is that the imported new flowchart/workflow/report uses fields of entities which are already available in the receiving instance.
- Go to the overview of whatever you want to copy (Flowcharts, Workflows via Administration; Reports is an entity so go the the List layout of this entity as a regular user)
- Select what you want to copy
- In the 'Actions' button, click 'Export'
- Select CSV as Format and export all fields
- Save it with a descriptive name
- Go to the Import module (Administration -> Data/Import)
- 'Entity Type': select what you want to import (note: flowcharts are called here Process Flowcharts)
- Upload your CSV
- Under 'What to do?', select 'Create Only'
- Click 'Next' and then 'Run Import'
- Confirm if the import status is Complete
Dynamic Logic parameters are available for every field (Administration) > Entity Manager > Fields
The Dynamic Logic allows to define conditions making certain fields visible, required or read-only. Conditions will be checked automatically when data in the form is changed.
For Enum, Array, Multi-Enum, Checklist fields it's possible to define different sets of options that will be available for the field depending on which condition is met. Note, that the order of option list is taken into account.
Dynamic logic can control:
Visibility − if the field is visible or not; Required − if the field is required or not; Read-only − if the field read-only or not; Options − conditions that determine which options are available (for Enum, Array, Multi-Enum, Checklist fields); Invalidity − conditions making the field invalid
Conditions are configured through user interface, no coding required.
Here are some scrips to efficiently set up advanced conditional options.
Add conditional options to an enum field (targetfield
) based on the values of another enum field (conditionalfield
).
Example: if conditionalfield
has values X and Y, then targetfield
can only have values X and Y.
See addEnumConditionalField.py
Under constructions, see CascadingSelect.py
It is best practice to remove unused data periodicallly. This is to avoid doing harm with unnecessary storing personal data and to make sure the database is kept clean.
Removing data can be done in multiple methods:
- With Flowcharts and Reports. This requires to purchase the EspoCRM Advanced Pack
- With a cron job on the VM that queries the database on specific conditions for deletion and then sets deleted = true
- With a central service (logic app or web app / API) that goes through all registered EspoCRM instances and deletes certain unused data.
Only the first method (flowcharts and reports) is currently implemented.
This solution requires the Advanced Package from EspoCRM and at least one report and one flowchart. For DEH, the following data retention flowchart and report have been made. This template will only work if there are Cases (specific entity from DEH) in your instance. If you have another entity that you want to remove records from, you can adjust these templates accordingly. The templates can be imported via the Import module in EspoCRM UI.
In EspoCRM, hooks are powerful mechanisms that enable us to inject custom logic and functionalities into the core operations of the CRM platform. Essentially, hooks act as event listeners, allowing us to intercept and modify the system's behaviour before or after specific events occur, such as creating, updating, or deleting records. These customizable entry points provide a way to extend and tailor EspoCRM to meet unique program requirements without directly modifying the core codebase.
Hooks serve as a bridge between the standard functionality of EspoCRM and the specific needs of a certain project, facilitating seamless integration of custom features, automated processes, and enhanced workflows. Whether it's enforcing data validation, triggering external processes, or implementing complex data validation / de-duplication rules (See IFRC de duplication work with SARC for example), hooks can allow us to adapt EspoCRM to our specific use cases, allowing for a more tailored and efficient EspoCRM experience.
There are essentially two types of hooks:
Entity Hooks are triggered before or after specific operations on records, such as creation, update, deletion, and retrieval. These hooks serve as predefined entry points for executing custom PHP code before or after these events. We can use this to execute tailored logic, which goes beyond the usual functionality of EspoCRM, by leveraging these hooks we can extend and customise EspoCRM without directly modifying the core codebase.
Here is an example of a very simple entity hook:
1. Create a Custom Field:
First, create a custom field named 'LastContactUpdate' in the 'Account' entity to store the timestamp of the last update from a related 'Contact' record.
2. Create an Entity Hook:
-
Next, create an Entity Hook to execute custom code when a 'Contact' record is created or updated.
-
Create a new PHP file in the custom/Espo/Custom/Resources/metadata/hooks/ directory, for example, AfterContactSave.php.
-
Add the following code to the file:
)
3. Clear cache:
- After creating the hook, clear the EspoCRM cache to ensure that the changes take effect.
This example demonstrates how an Entity Hook can be used to automatically update a custom field in the 'Account' entity whenever a 'Contact' record is created or updated. The 'LastContactUpdate' field in the 'Account' entity will be updated with the current timestamp whenever a related 'Contact' is modified, providing a way to track the last update from associated contacts for each record.
In EspoCRM, a metadata hook is a customization mechanism that allows you to modify and extend the metadata of the CRM application. Metadata encompasses the structural elements of the CRM, such as entities, fields, layouts, and relationships. A metadata hook provides a way to alter these components without directly modifying the core codebase.
Here's a simple example:
Imagine you want to add a new custom field to an entity in EspoCRM, such as adding a "Priority" field to the "Cases" entity. Instead of manually modifying the entity definition in the CRM's administration panel, you can use a metadata hook to achieve this programmatically.
In a metadata hook, you define a PHP class with methods corresponding to specific events, such as "beforeSaveEntity" or "afterMetadataLoaded." These methods allow you to interact with and modify the metadata of EspoCRM at different points in its execution.
See code example below:
In this example, the afterMetadataLoaded method is triggered after the metadata is loaded. It checks if the 'Cases' entity exists and then adds a new custom field named 'priority' to the 'Cases' entity.
By using metadata hooks, we can dynamically adjust the structure of EspoCRM to suit our needs without directly modifying core files, making it easier to manage customizations and updates.
Translations in EspoCRM can be done by changing the labels in the Label Manager. Since this can be a lot of work to translate manually, there is a special script to translate everything automatically. One can choose whether to translate only custom entities or the whole application. After automatic translation, one should still check the quality of the translations in the Label Manager and potentially add or edit translations. The preferred language can be selected by users by clicking on the three dots in the top-right of the screen and then selecting Language.
Bug fix: translate headers in the list view
In some cases the headings in the list-view are not translated even though the translations are correctly filled in the label manager. A solution has been found for this item by editing the EspoCRM backend:
- Go to
/var/www/espocrm/data/espocrm/custom/Espo/Custom/Resources/layouts
. - For each entity, go into its folder and delete
list.json
; this will enable the translations provided in the i18n folders to be used instead. - Repeat for
listSmall.json
.
Run translation script locally
- Clone repo locally
- Start docker
- Add the URL + keys of the translator to the script
- Open your terminal
- In the terminal, use commands provided in the readme
- In the terminal, build docker image with
docker build .
- Check image id with
docker image ls
- Run docker image with
docker run -p 8000:8000 [imageID]
- After run was done, open browser with localhost port 8000 (port was specified before) http://localhost:8000/
- Use the API
- If you like to see what docker containers are running use
docker ps -a
, also use this to check for the name - If you like to stop the docker container that is running use
docker stop [name]
- If you like to remove the docker container, make sure it stopped running and use
docker rm [name]
- If you like to remove the image use
docker image rm [imageID]