Skip to content

Customization

Emie Klein Holkenborg edited this page Oct 9, 2024 · 52 revisions

You can find documentation and step-by-step guide on how to customize EspoCRM.

Extensions

Introduction

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.

Structure

The file structure of the extension package:

  1. manifest.json – a file that contains extension properties such as name and version;
  2. files/ – a directory that contains extension files;
  3. 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

Creating an extension

Prerequisite: a file manager that can handle SSH, for this purpose, WinSCP is recommended, but PuTTY can most probably also be used

Steps:

  1. 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).
  2. In /var/www/espocrm/data/espocrm/ find the custom folder. Here all the custom entities + layouts + formulas + labels are stored.
  3. Copy the whole custom folder to your local computer (drag and drop in WinSCP)
  4. Structure of the "custom" folder: a "manifest.json" file and a "files" folder.
  5. Now on your local computer
    1. Create a new folder called "files" and copy the entire "custom" folder in "files". (Don't use the "client" folder if that exists).
    2. Create a template manifest file (copy-paste the deh "manifest.json") and place it on the same folder level next to the "files" folder
    3. 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.

Extension deployment

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.

1. Manual Deployment

Open your espo CRM, as an Admin, and navigate to the extensions page. Click on choose file and select the ZIP

upload extension

Once the Zip is selected click upload and you'll get this pop-up.

installation

Click on Install and that should apply the changes to your espo.

2. Via the command line in the Virtual Machine.

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.

Make custom entities and fields "non-deletable"

  • to make an Entity non-deletable set "isCustom": false in custom/Espo/Custom/Resources/metadata/scopes/<MyEntity>.json
  • to make a Field non-deletable set "isCustom": false under fields/<MyField> in custom/Espo/Custom/Resources/metadata/entityDefs/<MyEntity>.json

Calculate fields continuously without flowcharts

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)"
        },

Duplicate checking for custom fields

Click here

Create global filters for all users

Click here

Field validation with regex

Click here

Export and import flowcharts, workflows and reports

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.

Export

  1. 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)
  2. Select what you want to copy
  3. In the 'Actions' button, click 'Export'
  4. Select CSV as Format and export all fields
  5. Save it with a descriptive name

Import

  1. Go to the Import module (Administration -> Data/Import)
  2. 'Entity Type': select what you want to import (note: flowcharts are called here Process Flowcharts)
  3. Upload your CSV
  4. Under 'What to do?', select 'Create Only'
  5. Click 'Next' and then 'Run Import'
  6. Confirm if the import status is Complete

Fields Dynamic Logic

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.

Screenshot (519) Screenshot (520)

Conditional Options

Here are some scrips to efficiently set up advanced conditional options.

Cascading Enum Fields

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

Custom Cascading Select

Under constructions, see CascadingSelect.py

Data retention flowcharts

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:

  1. With Flowcharts and Reports. This requires to purchase the EspoCRM Advanced Pack
  2. With a cron job on the VM that queries the database on specific conditions for deletion and then sets deleted = true
  3. 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.

Removing data with flowcharts and reports

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.

Using hooks

What are hooks?

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.

Types of hooks

There are essentially two types of hooks:

Entity 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:

image)

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.

Metadata hooks:

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:

image

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

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

  1. Clone repo locally
  2. Start docker
  3. Add the URL + keys of the translator to the script
  4. Open your terminal
  5. In the terminal, use commands provided in the readme
  6. In the terminal, build docker image with docker build .
  7. Check image id with docker image ls
  8. Run docker image with docker run -p 8000:8000 [imageID]
  9. After run was done, open browser with localhost port 8000 (port was specified before) http://localhost:8000/
  10. Use the API
  11. If you like to see what docker containers are running use docker ps -a, also use this to check for the name
  12. If you like to stop the docker container that is running use docker stop [name]
  13. If you like to remove the docker container, make sure it stopped running and use docker rm [name]
  14. If you like to remove the image use docker image rm [imageID]